blob: 16962bcb3a8cf100c893bfeb1a9077976c04c3e1 [file] [log] [blame]
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/debugger/devtools_manager.h"
#include "base/message_loop.h"
#include "chrome/browser/debugger/devtools_window.h"
#include "chrome/browser/debugger/devtools_client_host.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/tab_contents/site_instance.h"
#include "chrome/common/devtools_messages.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "googleurl/src/gurl.h"
DevToolsManager::DevToolsManager()
: inspected_rvh_for_reopen_(NULL) {
}
DevToolsManager::~DevToolsManager() {
DCHECK(inspected_rvh_to_client_host_.empty());
DCHECK(client_host_to_inspected_rvh_.empty());
}
DevToolsClientHost* DevToolsManager::GetDevToolsClientHostFor(
RenderViewHost* inspected_rvh) {
InspectedRvhToClientHostMap::iterator it =
inspected_rvh_to_client_host_.find(inspected_rvh);
if (it != inspected_rvh_to_client_host_.end()) {
return it->second;
}
return NULL;
}
void DevToolsManager::RegisterDevToolsClientHostFor(
RenderViewHost* inspected_rvh,
DevToolsClientHost* client_host) {
DCHECK(!GetDevToolsClientHostFor(inspected_rvh));
inspected_rvh_to_client_host_[inspected_rvh] = client_host;
client_host_to_inspected_rvh_[client_host] = inspected_rvh;
client_host->set_close_listener(this);
SendAttachToAgent(inspected_rvh);
}
void DevToolsManager::ForwardToDevToolsAgent(
RenderViewHost* client_rvh,
const IPC::Message& message) {
for (InspectedRvhToClientHostMap::iterator it =
inspected_rvh_to_client_host_.begin();
it != inspected_rvh_to_client_host_.end();
++it) {
DevToolsWindow* win = it->second->AsDevToolsWindow();
if (!win) {
continue;
}
if (client_rvh == win->GetRenderViewHost()) {
ForwardToDevToolsAgent(win, message);
return;
}
}
}
void DevToolsManager::ForwardToDevToolsAgent(DevToolsClientHost* from,
const IPC::Message& message) {
RenderViewHost* inspected_rvh = GetInspectedRenderViewHost(from);
if (!inspected_rvh) {
// TODO(yurys): notify client that the agent is no longer available
NOTREACHED();
return;
}
IPC::Message* m = new IPC::Message(message);
m->set_routing_id(inspected_rvh->routing_id());
inspected_rvh->Send(m);
}
void DevToolsManager::ForwardToDevToolsClient(RenderViewHost* inspected_rvh,
const IPC::Message& message) {
DevToolsClientHost* client_host = GetDevToolsClientHostFor(inspected_rvh);
if (!client_host) {
// Client window was closed while there were messages
// being sent to it.
return;
}
client_host->SendMessageToClient(message);
}
void DevToolsManager::OpenDevToolsWindow(RenderViewHost* inspected_rvh) {
DevToolsClientHost* host = GetDevToolsClientHostFor(inspected_rvh);
if (!host) {
host = new DevToolsWindow(
inspected_rvh->site_instance()->browsing_instance()->profile());
RegisterDevToolsClientHostFor(inspected_rvh, host);
}
DevToolsWindow* window = host->AsDevToolsWindow();
if (window)
window->Show();
}
void DevToolsManager::InspectElement(RenderViewHost* inspected_rvh,
int x,
int y) {
OpenDevToolsWindow(inspected_rvh);
IPC::Message* m = new DevToolsAgentMsg_InspectElement(x, y);
m->set_routing_id(inspected_rvh->routing_id());
inspected_rvh->Send(m);
}
void DevToolsManager::ClientHostClosing(DevToolsClientHost* host) {
RenderViewHost* inspected_rvh = GetInspectedRenderViewHost(host);
if (!inspected_rvh) {
return;
}
SendDetachToAgent(inspected_rvh);
inspected_rvh_to_client_host_.erase(inspected_rvh);
client_host_to_inspected_rvh_.erase(host);
}
RenderViewHost* DevToolsManager::GetInspectedRenderViewHost(
DevToolsClientHost* client_host) {
ClientHostToInspectedRvhMap::iterator it =
client_host_to_inspected_rvh_.find(client_host);
if (it != client_host_to_inspected_rvh_.end()) {
return it->second;
}
return NULL;
}
void DevToolsManager::UnregisterDevToolsClientHostFor(
RenderViewHost* inspected_rvh) {
DevToolsClientHost* host = GetDevToolsClientHostFor(inspected_rvh);
if (!host) {
return;
}
host->InspectedTabClosing();
inspected_rvh_to_client_host_.erase(inspected_rvh);
client_host_to_inspected_rvh_.erase(host);
if (inspected_rvh_for_reopen_ == inspected_rvh) {
inspected_rvh_for_reopen_ = NULL;
}
}
void DevToolsManager::OnNavigatingToPendingEntry(RenderViewHost* rvh,
RenderViewHost* dest_rvh,
const GURL& gurl) {
DevToolsClientHost* client_host =
GetDevToolsClientHostFor(rvh);
if (client_host) {
// Navigating to URL in the inspected window.
inspected_rvh_to_client_host_.erase(rvh);
inspected_rvh_to_client_host_[dest_rvh] = client_host;
client_host_to_inspected_rvh_[client_host] = dest_rvh;
SendAttachToAgent(dest_rvh);
return;
}
// Iterate over client hosts and if there is one that has render view host
// changing, reopen entire client window (this must be caused by the user
// manually refreshing its content).
for (ClientHostToInspectedRvhMap::iterator it =
client_host_to_inspected_rvh_.begin();
it != client_host_to_inspected_rvh_.end(); ++it) {
DevToolsWindow* window = it->first->AsDevToolsWindow();
if (window && window->GetRenderViewHost() == rvh) {
RenderViewHost* inspected_rvn = it->second;
UnregisterDevToolsClientHostFor(inspected_rvn);
SendDetachToAgent(inspected_rvn);
inspected_rvh_for_reopen_ = inspected_rvn;
MessageLoop::current()->PostTask(FROM_HERE,
NewRunnableMethod(this,
&DevToolsManager::ForceReopenWindow));
return;
}
}
}
void DevToolsManager::SendAttachToAgent(RenderViewHost* inspected_rvh) {
if (inspected_rvh) {
IPC::Message* m = new DevToolsAgentMsg_Attach();
m->set_routing_id(inspected_rvh->routing_id());
inspected_rvh->Send(m);
}
}
void DevToolsManager::SendDetachToAgent(RenderViewHost* inspected_rvh) {
if (inspected_rvh) {
IPC::Message* m = new DevToolsAgentMsg_Detach();
m->set_routing_id(inspected_rvh->routing_id());
inspected_rvh->Send(m);
}
}
void DevToolsManager::ForceReopenWindow() {
if (inspected_rvh_for_reopen_) {
OpenDevToolsWindow(inspected_rvh_for_reopen_);
inspected_rvh_for_reopen_ = NULL;
}
}