// 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 #include "base/command_line.h" #include "base/message_loop.h" #include "base/process.h" #include "base/string_number_conversions.h" #include "content/common/devtools_messages.h" #include "content/common/view_messages.h" #include "content/public/common/content_switches.h" #include "content/renderer/devtools_agent_filter.h" #include "content/renderer/devtools_client.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 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::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(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_; }