blob: d7f6a63a46a836de7d9596fbe69e0c73b4f26e8b [file] [log] [blame]
// Copyright (c) 2011 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 "content/renderer/devtools_agent.h"
#include <map>
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/process.h"
#include "base/string_number_conversions.h"
#include "content/common/content_switches.h"
#include "content/renderer/devtools_agent_filter.h"
#include "content/renderer/devtools_client.h"
#include "content/common/devtools_messages.h"
#include "content/common/view_messages.h"
#include "content/renderer/render_view_impl.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
using WebKit::WebDevToolsAgent;
using WebKit::WebDevToolsAgentClient;
using WebKit::WebPoint;
using WebKit::WebString;
using WebKit::WebCString;
using WebKit::WebVector;
using WebKit::WebView;
namespace {
class WebKitClientMessageLoopImpl
: public WebDevToolsAgentClient::WebKitClientMessageLoop {
public:
WebKitClientMessageLoopImpl() : message_loop_(MessageLoop::current()) { }
virtual ~WebKitClientMessageLoopImpl() {
message_loop_ = NULL;
}
virtual void run() {
bool old_state = message_loop_->NestableTasksAllowed();
message_loop_->SetNestableTasksAllowed(true);
message_loop_->Run();
message_loop_->SetNestableTasksAllowed(old_state);
}
virtual void quitNow() {
message_loop_->QuitNow();
}
private:
MessageLoop* message_loop_;
};
} // namespace
// static
std::map<int, DevToolsAgent*> DevToolsAgent::agent_for_routing_id_;
DevToolsAgent::DevToolsAgent(RenderViewImpl* render_view)
: content::RenderViewObserver(render_view),
is_attached_(false) {
agent_for_routing_id_[routing_id()] = this;
CommandLine* cmd = CommandLine::ForCurrentProcess();
expose_v8_debugger_protocol_ = cmd->HasSwitch(switches::kRemoteShellPort);
render_view->webview()->setDevToolsAgentClient(this);
render_view->webview()->devToolsAgent()->setProcessId(
base::Process::Current().pid());
}
DevToolsAgent::~DevToolsAgent() {
agent_for_routing_id_.erase(routing_id());
}
// Called on the Renderer thread.
bool DevToolsAgent::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(DevToolsAgent, message)
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Attach, OnAttach)
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Reattach, OnReattach)
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Detach, OnDetach)
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_FrontendLoaded, OnFrontendLoaded)
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend,
OnDispatchOnInspectorBackend)
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_InspectElement, OnInspectElement)
IPC_MESSAGE_HANDLER(DevToolsMsg_SetupDevToolsClient, OnSetupDevToolsClient)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
if (message.type() == ViewMsg_Navigate::ID)
OnNavigate(); // Don't want to swallow the message.
return handled;
}
void DevToolsAgent::sendMessageToInspectorFrontend(
const WebKit::WebString& message) {
Send(new DevToolsHostMsg_ForwardToClient(
routing_id(),
DevToolsClientMsg_DispatchOnInspectorFrontend(MSG_ROUTING_NONE,
message.utf8())));
}
void DevToolsAgent::sendDebuggerOutput(const WebKit::WebString& data) {
Send(new DevToolsHostMsg_ForwardToClient(
routing_id(),
DevToolsClientMsg_DebuggerOutput(MSG_ROUTING_NONE, data.utf8())));
}
int DevToolsAgent::hostIdentifier() {
return routing_id();
}
void DevToolsAgent::saveAgentRuntimeState(
const WebKit::WebString& state) {
Send(new DevToolsHostMsg_SaveAgentRuntimeState(routing_id(), state.utf8()));
}
WebKit::WebDevToolsAgentClient::WebKitClientMessageLoop*
DevToolsAgent::createClientMessageLoop() {
return new WebKitClientMessageLoopImpl();
}
bool DevToolsAgent::exposeV8DebuggerProtocol() {
return expose_v8_debugger_protocol_;
}
void DevToolsAgent::clearBrowserCache() {
Send(new DevToolsHostMsg_ClearBrowserCache(routing_id()));
}
void DevToolsAgent::clearBrowserCookies() {
Send(new DevToolsHostMsg_ClearBrowserCookies(routing_id()));
}
// static
DevToolsAgent* DevToolsAgent::FromHostId(int host_id) {
std::map<int, DevToolsAgent*>::iterator it =
agent_for_routing_id_.find(host_id);
if (it != agent_for_routing_id_.end()) {
return it->second;
}
return NULL;
}
void DevToolsAgent::OnAttach() {
WebDevToolsAgent* web_agent = GetWebAgent();
if (web_agent) {
web_agent->attach();
is_attached_ = true;
}
}
void DevToolsAgent::OnReattach(const std::string& agent_state) {
WebDevToolsAgent* web_agent = GetWebAgent();
if (web_agent) {
web_agent->reattach(WebString::fromUTF8(agent_state));
is_attached_ = true;
}
}
void DevToolsAgent::OnDetach() {
WebDevToolsAgent* web_agent = GetWebAgent();
if (web_agent) {
web_agent->detach();
is_attached_ = false;
}
}
void DevToolsAgent::OnFrontendLoaded() {
WebDevToolsAgent* web_agent = GetWebAgent();
if (web_agent)
web_agent->frontendLoaded();
}
void DevToolsAgent::OnDispatchOnInspectorBackend(const std::string& message) {
WebDevToolsAgent* web_agent = GetWebAgent();
if (web_agent)
web_agent->dispatchOnInspectorBackend(WebString::fromUTF8(message));
}
void DevToolsAgent::OnInspectElement(int x, int y) {
WebDevToolsAgent* web_agent = GetWebAgent();
if (web_agent) {
web_agent->attach();
web_agent->inspectElementAt(WebPoint(x, y));
}
}
void DevToolsAgent::OnNavigate() {
WebDevToolsAgent* web_agent = GetWebAgent();
if (web_agent) {
web_agent->didNavigate();
}
}
void DevToolsAgent::OnSetupDevToolsClient() {
new DevToolsClient(static_cast<RenderViewImpl*>(render_view()));
}
WebDevToolsAgent* DevToolsAgent::GetWebAgent() {
WebView* web_view = render_view()->GetWebView();
if (!web_view)
return NULL;
return web_view->devToolsAgent();
}
bool DevToolsAgent::IsAttached() {
return is_attached_;
}