diff options
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/dev_tools_agent.cc | 143 | ||||
-rw-r--r-- | chrome/renderer/dev_tools_agent.h | 69 | ||||
-rw-r--r-- | chrome/renderer/dev_tools_client.cc | 41 | ||||
-rw-r--r-- | chrome/renderer/dev_tools_client.h | 43 | ||||
-rw-r--r-- | chrome/renderer/dev_tools_messages.h | 12 | ||||
-rw-r--r-- | chrome/renderer/dev_tools_messages_internal.h | 79 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 18 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 14 | ||||
-rw-r--r-- | chrome/renderer/renderer.scons | 6 | ||||
-rw-r--r-- | chrome/renderer/renderer.vcproj | 24 |
10 files changed, 449 insertions, 0 deletions
diff --git a/chrome/renderer/dev_tools_agent.cc b/chrome/renderer/dev_tools_agent.cc new file mode 100644 index 0000000..891e895 --- /dev/null +++ b/chrome/renderer/dev_tools_agent.cc @@ -0,0 +1,143 @@ +// 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/renderer/dev_tools_agent.h" + +#include "base/message_loop.h" +#include "chrome/common/render_messages.h" +#include "chrome/renderer/dev_tools_messages.h" +// TODO(yurys): remove this macros once plugins available on other platforms +#if defined(OS_WIN) +#include "chrome/renderer/plugin_channel_host.h" +#endif // OS_WIN +#include "chrome/renderer/render_process.h" +#include "chrome/renderer/render_view.h" + +DevToolsAgent::DevToolsAgent(RenderView* view, MessageLoop* view_loop) + : debugger_(NULL), + view_(view), + view_loop_(view_loop), + channel_(NULL), + io_loop_(NULL) { +} + +DevToolsAgent::~DevToolsAgent() { +} + +void DevToolsAgent::Send(const IPC::Message& tools_client_message) { + // It's possible that this will get cleared out from under us. + MessageLoop* io_loop = io_loop_; + if (!io_loop) + return; + + IPC::Message* m = new ViewHostMsg_ForwardToDevToolsClient( + view_->routing_id(), + tools_client_message); + io_loop->PostTask(FROM_HERE, NewRunnableMethod( + this, &DevToolsAgent::SendFromIOThread, m)); +} + +void DevToolsAgent::SendFromIOThread(IPC::Message* message) { + if (channel_) { + channel_->Send(message); + } else { + delete message; + } +} + +// Called on IO thread. +void DevToolsAgent::OnFilterAdded(IPC::Channel* channel) { + io_loop_ = MessageLoop::current(); + channel_ = channel; +} + +// Called on IO thread. +bool DevToolsAgent::OnMessageReceived(const IPC::Message& message) { + DCHECK(MessageLoop::current() == io_loop_); + + if (message.routing_id() != view_->routing_id()) + return false; + + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(DevToolsAgent, message) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DebugAttach, OnDebugAttach) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DebugDetach, OnDebugDetach) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DebugBreak, OnDebugBreak) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DebugCommand, OnDebugCommand) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void DevToolsAgent::OnFilterRemoved() { + io_loop_ = NULL; + channel_ = NULL; +} + +void DevToolsAgent::DebuggerOutput(const std::wstring& out) { + Send(DevToolsClientMsg_DebuggerOutput(out)); +} + +void DevToolsAgent::EvaluateScript(const std::wstring& script) { + DCHECK(MessageLoop::current() == view_loop_); + view_->EvaluateScript(L"", script); +} + +void DevToolsAgent::OnDebugAttach() { + DCHECK(MessageLoop::current() == io_loop_); + if (!debugger_) { + debugger_ = new DebuggerBridge(this); + } + + debugger_->Attach(); + + Send(DevToolsClientMsg_DidDebugAttach()); + + // TODO(yurys): remove this macros once plugins available on other platforms +#if defined(OS_WIN) + // Tell the plugin host to stop accepting messages in order to avoid + // hangs while the renderer is paused. + // TODO(yurys): It might be an improvement to add more plumbing to do this + // when the renderer is actually paused vs. just the debugger being attached. + // http://code.google.com/p/chromium/issues/detail?id=7556 + PluginChannelHost::SetListening(false); +#endif // OS_WIN +} + +void DevToolsAgent::OnDebugDetach() { + DCHECK(MessageLoop::current() == io_loop_); + if (debugger_) + debugger_->Detach(); + // TODO(yurys): remove this macros once plugins available on other platforms +#if defined(OS_WIN) + PluginChannelHost::SetListening(true); +#endif // OS_WIN +} + +void DevToolsAgent::OnDebugBreak(bool force) { + DCHECK(MessageLoop::current() == io_loop_); + // Set the debug break flag in the V8 engine. + debugger_->Break(force); + + // If a forced break has been requested make sure that it will occour by + // running some JavaScript in the renderer. + if (force && view_loop_) { + view_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &DevToolsAgent::EvaluateScript, + std::wstring(L"javascript:void(0)"))); + } +} + +void DevToolsAgent::OnDebugCommand(const std::wstring& cmd) { + DCHECK(MessageLoop::current() == io_loop_); + if (!debugger_) { + NOTREACHED(); + std::wstring msg = + StringPrintf(L"before attach, ignored command (%S)", cmd.c_str()); + DebuggerOutput(msg); + } else { + debugger_->Command(cmd); + } +} + diff --git a/chrome/renderer/dev_tools_agent.h b/chrome/renderer/dev_tools_agent.h new file mode 100644 index 0000000..c8c749e --- /dev/null +++ b/chrome/renderer/dev_tools_agent.h @@ -0,0 +1,69 @@ +// 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. + +#ifndef CHROME_RENDERER_DEV_TOOLS_AGENT_H_ +#define CHROME_RENDERER_DEV_TOOLS_AGENT_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "chrome/common/ipc_channel_proxy.h" +#include "webkit/glue/debugger_bridge.h" + +class MessageLoop; +class RenderView; + +// Inspected page end of communication channel between the render process of +// the page being inspected and tools UI renderer process. All messages will +// go through browser process. On the renderer side of the tools UI there's +// a corresponding ToolsClient object. +class DevToolsAgent : public IPC::ChannelProxy::MessageFilter, + public DebuggerBridge::Delegate { + public: + // DevToolsAgent is a field of the RenderView. The view is supposed to remove + // this agent from message filter list on IO thread before dying. + explicit DevToolsAgent(RenderView* view, MessageLoop* view_loop); + virtual ~DevToolsAgent(); + + private: + // Sends message to DevToolsClient. May be called on any thread. + void Send(const IPC::Message& tools_client_message); + + // Sends message to DevToolsClient. Must be called on IO thread. Takes + // ownership of the message. + void SendFromIOThread(IPC::Message* message); + + // IPC::ChannelProxy::MessageFilter overrides. Called on IO thread. + virtual void OnFilterAdded(IPC::Channel* channel); + virtual bool OnMessageReceived(const IPC::Message& message); + virtual void OnFilterRemoved(); + + // Debugger::Delegate callback method to handle debugger output. + void DebuggerOutput(const std::wstring& out); + + // Evaluate javascript URL in the renderer + void EvaluateScript(const std::wstring& script); + + // All these OnXXX methods will be executed in IO thread so that we can + // handle debug messages even when v8 is stopped. + void OnDebugAttach(); + void OnDebugDetach(); + void OnDebugBreak(bool force); + void OnDebugCommand(const std::wstring& cmd); + + scoped_refptr<DebuggerBridge> debugger_; + + RenderView* view_; + MessageLoop* view_loop_; + + IPC::Channel* channel_; + MessageLoop* io_loop_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsAgent); +}; + +#endif // CHROME_RENDERER_DEV_TOOLS_AGENT_H_ + diff --git a/chrome/renderer/dev_tools_client.cc b/chrome/renderer/dev_tools_client.cc new file mode 100644 index 0000000..6061c92 --- /dev/null +++ b/chrome/renderer/dev_tools_client.cc @@ -0,0 +1,41 @@ +// 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/renderer/dev_tools_client.h" + +#include "chrome/common/render_messages.h" +#include "chrome/renderer/dev_tools_messages.h" +#include "chrome/renderer/render_thread.h" +#include "chrome/renderer/render_view.h" + +DevToolsClient::DevToolsClient(RenderView* view) + : render_view_(view) { +} + +DevToolsClient::~DevToolsClient() { +} + +void DevToolsClient::Send(const IPC::Message& tools_agent_message) { + render_view_->Send(new ViewHostMsg_ForwardToDevToolsAgent( + render_view_->routing_id(), + tools_agent_message)); +} + +bool DevToolsClient::OnMessageReceived(const IPC::Message& message) { + DCHECK(RenderThread::current()->message_loop() == MessageLoop::current()); + + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(DevToolsClient, message) + IPC_MESSAGE_HANDLER(DevToolsClientMsg_DidDebugAttach, DidDebugAttach) + IPC_MESSAGE_UNHANDLED(handled = false); + IPC_END_MESSAGE_MAP() + + return handled; +} + +void DevToolsClient::DidDebugAttach() { + DCHECK(RenderThread::current()->message_loop() == MessageLoop::current()); + // TODO(yurys): delegate to JS frontend. +} + diff --git a/chrome/renderer/dev_tools_client.h b/chrome/renderer/dev_tools_client.h new file mode 100644 index 0000000..d3dfdf1 --- /dev/null +++ b/chrome/renderer/dev_tools_client.h @@ -0,0 +1,43 @@ +// 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. + +#ifndef CHROME_RENDERER_DEV_TOOLS_CLIENT_H_ +#define CHROME_RENDERER_DEV_TOOLS_CLIENT_H_ + +#include "base/basictypes.h" + +namespace IPC { +class Message; +} +class MessageLoop; +class RenderView; + +// Developer tools UI end of communication channel between the render process of +// the page being inspected and tools UI renderer process. All messages will +// go through browser process. On the side of the inspected page there's +// corresponding DevToolsAgent object. +// TODO(yurys): now the client is almost empty later it will delegate calls to +// code in glue +class DevToolsClient { + public: + explicit DevToolsClient(RenderView* view); + virtual ~DevToolsClient(); + + // Called to possibly handle the incoming IPC message. Returns true if + // handled. Called in render thread. + bool OnMessageReceived(const IPC::Message& message); + + private: + void DidDebugAttach(); + + // Sends message to DevToolsAgent. + void Send(const IPC::Message& tools_agent_message); + + RenderView* render_view_; // host render view + + DISALLOW_COPY_AND_ASSIGN(DevToolsClient); +}; + +#endif // CHROME_RENDERER_DEV_TOOLS_CLIENT_H_ + diff --git a/chrome/renderer/dev_tools_messages.h b/chrome/renderer/dev_tools_messages.h new file mode 100644 index 0000000..9225c2e --- /dev/null +++ b/chrome/renderer/dev_tools_messages.h @@ -0,0 +1,12 @@ +// 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. + +#ifndef CHROME_RENDERER_DEV_TOOLS_MESSAGES_H_ +#define CHROME_RENDERER_DEV_TOOLS_MESSAGES_H_ + +#define MESSAGES_INTERNAL_FILE "chrome/renderer/dev_tools_messages_internal.h" +#include "chrome/common/ipc_message_macros.h" + +#endif // CHROME_RENDERER_DEV_TOOLS_MESSAGES_H_ + diff --git a/chrome/renderer/dev_tools_messages_internal.h b/chrome/renderer/dev_tools_messages_internal.h new file mode 100644 index 0000000..9a1f8b5 --- /dev/null +++ b/chrome/renderer/dev_tools_messages_internal.h @@ -0,0 +1,79 @@ +// 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. + +// This header is meant to be included in multiple passes, hence no traditional +// header guard. +// See ipc_message_macros.h for explanation of the macros and passes. + +// Developer tools consist of the following parts: +// +// DevToolsAgent lives in the renderer of an inspected page and provides access +// to the pages resources, DOM, v8 etc. by means of IPC messages. +// +// DevToolsClient is a thin delegate that lives in the tools front-end renderer +// and converts IPC messages to frontend method calls and allows the frontend +// to send messages to the DevToolsAgent. +// +// All the messages are routed through browser process. +// +// Chain of communication between the components may be described by the +// following diagram: +// ---------------------------- +// | (tools frontend | +// | renderer process) | +// | | -------------------- +// |tools <--> DevToolsClient+<-- IPC -->+ (browser process) | +// |frontend | | | +// ---------------------------- ---------+---------- +// ^ +// | +// IPC +// | +// v +// --------------------------+-------- +// | inspected page <--> DevToolsAgent | +// | | +// | (inspected page renderer process) | +// ----------------------------------- +// +// This file describes developer tools message types. + +#include "chrome/common/ipc_message_macros.h" + +// These are messages sent from DevToolsAgent to DevToolsClient through the +// browser. +IPC_BEGIN_MESSAGES(DevToolsClient) + + // Response message for DevToolsAgentMsg_DebugAttach. + IPC_MESSAGE_CONTROL0(DevToolsClientMsg_DidDebugAttach) + + // WebKit and JavaScript error messages to log to the console + // or debugger UI. + IPC_MESSAGE_CONTROL1(DevToolsClientMsg_DebuggerOutput, + std::wstring /* msg */) + +IPC_END_MESSAGES(DevToolsClient) + + +//----------------------------------------------------------------------------- +// These are messages sent from DevToolsClient to DevToolsAgent through the +// browser. +IPC_BEGIN_MESSAGES(DevToolsAgent) + + // Initialize the V8 debugger in the renderer. + IPC_MESSAGE_CONTROL0(DevToolsAgentMsg_DebugAttach) + + // Shutdown the V8 debugger in the renderer. + IPC_MESSAGE_CONTROL0(DevToolsAgentMsg_DebugDetach) + + // Break V8 execution. + IPC_MESSAGE_CONTROL1(DevToolsAgentMsg_DebugBreak, + bool /* force */) + + // Send a command to the V8 debugger. + IPC_MESSAGE_CONTROL1(DevToolsAgentMsg_DebugCommand, + std::wstring /* cmd */) + +IPC_END_MESSAGES(DevToolsAgent) + diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 8621085..91efbf4 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -26,6 +26,8 @@ #include "chrome/common/url_constants.h" #include "chrome/renderer/about_handler.h" #include "chrome/renderer/debug_message_handler.h" +#include "chrome/renderer/dev_tools_agent.h" +#include "chrome/renderer/dev_tools_client.h" #include "chrome/renderer/localized_error.h" #include "chrome/renderer/media/audio_renderer_impl.h" #include "chrome/renderer/render_process.h" @@ -169,6 +171,8 @@ RenderView::RenderView(RenderThreadBase* render_thread) method_factory_(this), first_default_plugin_(NULL), printed_document_width_(0), + dev_tools_agent_(NULL), + dev_tools_client_(NULL), history_back_list_count_(0), history_forward_list_count_(0), disable_popup_blocking_(false), @@ -197,6 +201,7 @@ RenderView::~RenderView() { } render_thread_->RemoveFilter(debug_message_handler_); + render_thread_->RemoveFilter(dev_tools_agent_); #ifdef CHROME_PERSONALIZATION Personalization::CleanupRendererPersonalization(personalization_); @@ -314,6 +319,9 @@ void RenderView::Init(gfx::NativeViewId parent_hwnd, debug_message_handler_ = new DebugMessageHandler(this); render_thread_->AddFilter(debug_message_handler_); + + dev_tools_agent_ = new DevToolsAgent(this, MessageLoop::current()); + render_thread_->AddFilter(dev_tools_agent_); } void RenderView::OnMessageReceived(const IPC::Message& message) { @@ -333,6 +341,10 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { if (resource_dispatcher_->OnMessageReceived(message)) return; + // If this is developer tools renderer intercept tools messages first. + if (dev_tools_client_.get() && dev_tools_client_->OnMessageReceived(message)) + return; + IPC_BEGIN_MESSAGE_MAP(RenderView, message) IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck) IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail) @@ -356,6 +368,7 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding) IPC_MESSAGE_HANDLER(ViewMsg_InspectElement, OnInspectElement) IPC_MESSAGE_HANDLER(ViewMsg_ShowJavaScriptConsole, OnShowJavaScriptConsole) + IPC_MESSAGE_HANDLER(ViewMsg_SetupDevToolsClient, OnSetupDevToolsClient) IPC_MESSAGE_HANDLER(ViewMsg_DownloadImage, OnDownloadImage) IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest) IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole) @@ -904,6 +917,11 @@ void RenderView::OnShowJavaScriptConsole() { webview()->ShowJavaScriptConsole(); } +void RenderView::OnSetupDevToolsClient() { + DCHECK(!dev_tools_client_.get()); + dev_tools_client_.reset(new DevToolsClient(this)); +} + void RenderView::OnStopFinding(bool clear_selection) { WebView* view = webview(); if (!view) diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 6202f7a..b4a39bb 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -44,6 +44,8 @@ class AudioRendererImpl; class DictionaryValue; class DebugMessageHandler; +class DevToolsAgent; +class DevToolsClient; class FilePath; class GlueAccessibility; class GURL; @@ -460,6 +462,7 @@ class RenderView : public RenderWidget, void OnCopyImageAt(int x, int y); void OnInspectElement(int x, int y); void OnShowJavaScriptConsole(); + void OnSetupDevToolsClient(); void OnCancelDownload(int32 download_id); void OnFind(const FindInPageRequest& request); void OnZoom(int function); @@ -590,6 +593,10 @@ class RenderView : public RenderWidget, // information to the browser process. void BindDOMAutomationController(WebFrame* webframe); + // Creates DevToolsClient and sets up JavaScript bindings for developer tools + // UI that is going to be hosted by this RenderView. + void CreateDevToolsClient(); + void set_opened_by_user_gesture(bool value) { opened_by_user_gesture_ = value; } @@ -732,6 +739,13 @@ class RenderView : public RenderWidget, scoped_refptr<DebugMessageHandler> debug_message_handler_; + // Provides access to this renderer from the remote Inspector UI. + scoped_refptr<DevToolsAgent> dev_tools_agent_; + + // DevToolsClient for renderer hosting developer tools UI. It's NULL for other + // render views. + scoped_ptr<DevToolsClient> dev_tools_client_; + scoped_ptr<WebFileChooserCallback> file_chooser_; int history_back_list_count_; diff --git a/chrome/renderer/renderer.scons b/chrome/renderer/renderer.scons index 2522959..85bfde1 100644 --- a/chrome/renderer/renderer.scons +++ b/chrome/renderer/renderer.scons @@ -66,6 +66,12 @@ input_files = ChromeFileList([ 'chrome_plugin_host.h', 'debug_message_handler.cc', 'debug_message_handler.h', + 'dev_tools_agent.cc', + 'dev_tools_agent.h', + 'dev_tools_client.cc', + 'dev_tools_client.h', + 'dev_tools_messages.h', + 'dev_tools_messages_internal.h', 'dom_ui_bindings.cc', 'dom_ui_bindings.h', 'external_host_bindings.cc', diff --git a/chrome/renderer/renderer.vcproj b/chrome/renderer/renderer.vcproj index caa5e20..8e81aac 100644 --- a/chrome/renderer/renderer.vcproj +++ b/chrome/renderer/renderer.vcproj @@ -206,6 +206,30 @@ > </File> <File + RelativePath=".\dev_tools_agent.cc" + > + </File> + <File + RelativePath=".\dev_tools_agent.h" + > + </File> + <File + RelativePath=".\dev_tools_client.cc" + > + </File> + <File + RelativePath=".\dev_tools_client.h" + > + </File> + <File + RelativePath=".\dev_tools_messages.h" + > + </File> + <File + RelativePath=".\dev_tools_messages_internal.h" + > + </File> + <File RelativePath=".\dom_ui_bindings.cc" > </File> |