diff options
author | yurys@google.com <yurys@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-26 12:39:28 +0000 |
---|---|---|
committer | yurys@google.com <yurys@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-26 12:39:28 +0000 |
commit | b2abac7f32280c9d8bd0fd0d23c5432701634807 (patch) | |
tree | 62adfb69a3a725900cbd812c006622287bbb7c75 | |
parent | b5df94ed369ac59a76e81fb8a13552cac449509f (diff) | |
download | chromium_src-b2abac7f32280c9d8bd0fd0d23c5432701634807.zip chromium_src-b2abac7f32280c9d8bd0fd0d23c5432701634807.tar.gz chromium_src-b2abac7f32280c9d8bd0fd0d23c5432701634807.tar.bz2 |
DevToolsAgent provides IPC access to the inspected page from developer tools.
RenderView running developer tools front-end instantiates DevToolsClient that handles IPC communication with DevToolsAgent.
All messages are wrapped and routed through browser process.
darin: please look at changes related to messages handling in RenderView
jam: please review handling of forwarded messages in DevToolsClient and DevToolsAgent.
Review URL: http://codereview.chromium.org/21543
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10459 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/chrome.xcodeproj/project.pbxproj | 16 | ||||
-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 |
11 files changed, 465 insertions, 0 deletions
diff --git a/chrome/chrome.xcodeproj/project.pbxproj b/chrome/chrome.xcodeproj/project.pbxproj index 2f2af3d..9550646 100644 --- a/chrome/chrome.xcodeproj/project.pbxproj +++ b/chrome/chrome.xcodeproj/project.pbxproj @@ -90,6 +90,7 @@ 261AA15DB2FF0FA9B0E63ACF /* automation_provider.cc in Sources */ = {isa = PBXBuildFile; fileRef = E48FB9640EC4EA270052B72B /* automation_provider.cc */; }; 2760C4346D6AB3AD94E9CF05 /* url_fixer_upper.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5D16EF40F2145C600861FAC /* url_fixer_upper.cc */; }; 28283DBE4B6DB2B0F9893676 /* dns_master.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D7BFA6D0E9D4981009A6919 /* dns_master.cc */; }; + 29D0CE7BEF15AE6D5233BA6A /* dev_tools_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2F904214F0F0BA780D8DC4C9 /* dev_tools_client.cc */; }; 2D70E0E2053C6C759EC97929 /* chrome_plugin_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D7BFB950E9D4C9F009A6919 /* chrome_plugin_util.cc */; }; 2DF2A9EB8AF96926EE9B6B02 /* ipc_logging.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D7BFBAE0E9D4C9F009A6919 /* ipc_logging.cc */; }; 3257B6150A16A88F55E5AE34 /* bookmark_drop_info.cc in Sources */ = {isa = PBXBuildFile; fileRef = 12F137DA942221A44BFA0967 /* bookmark_drop_info.cc */; }; @@ -134,6 +135,7 @@ 3380A9D60F2FC8F6004EF74F /* render_dns_master.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D640CE10EAE86A500EBCFC0 /* render_dns_master.cc */; }; 3380A9D70F2FC8F9004EF74F /* render_dns_master.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D640CE10EAE86A500EBCFC0 /* render_dns_master.cc */; }; 34A17287EFE747DE84BAE6E6 /* session_restore.cc in Sources */ = {isa = PBXBuildFile; fileRef = C3F9577C67188A5A4E3A6E41 /* session_restore.cc */; }; + 3569E82DB055CE4B8E329CCC /* dev_tools_agent.cc in Sources */ = {isa = PBXBuildFile; fileRef = D792830F807C366EAB752D69 /* dev_tools_agent.cc */; }; 36F859CE61900AFD2AB67A91 /* save_item.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D7BF9D80E9D48CE009A6919 /* save_item.cc */; }; 3AEA44DB19C9D93B63D7A2E4 /* url_fetcher_protect.cc in Sources */ = {isa = PBXBuildFile; fileRef = 0B7CC9C105E90E0665852528 /* url_fetcher_protect.cc */; }; 406DFE278638D6132B21B2C9 /* url_pattern.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6447F24FADC63E58A44DB762 /* url_pattern.cc */; }; @@ -1962,12 +1964,15 @@ 0082A7520F16987A000AA0EF /* user_script_master.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user_script_master.h; sourceTree = "<group>"; }; 0114EE7E1097BDFBF94057E6 /* search_provider.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = search_provider.cc; path = browser/autocomplete/search_provider.cc; sourceTree = SOURCE_ROOT; }; 05C9D404FC8116984CCCEDED /* base_session_service.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = base_session_service.cc; path = sessions/base_session_service.cc; sourceTree = "<group>"; }; + 07FE4EE1A3A0636A63757967 /* dev_tools_agent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dev_tools_agent.h; sourceTree = "<group>"; }; 0B7CC9C105E90E0665852528 /* url_fetcher_protect.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = url_fetcher_protect.cc; sourceTree = "<group>"; }; + 0DF4243691A34E9B11373400 /* dev_tools_messages_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dev_tools_messages_internal.h; sourceTree = "<group>"; }; 12F137DA942221A44BFA0967 /* bookmark_drop_info.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bookmark_drop_info.cc; path = browser/bookmarks/bookmark_drop_info.cc; sourceTree = SOURCE_ROOT; }; 1F43A7C85092C58AAF011F78 /* greasemonkey_api_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = greasemonkey_api_unittest.cc; path = extensions/greasemonkey_api_unittest.cc; sourceTree = "<group>"; }; 269003C4E493789D82B6B0F9 /* history_publisher.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = history_publisher.cc; sourceTree = "<group>"; }; 26D97CE692D919FEB1521E43 /* ssl_error_info.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ssl_error_info.cc; path = ssl/ssl_error_info.cc; sourceTree = "<group>"; }; 28AA584AB2ECFB33C7C7FD8A /* template_url_parser.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = template_url_parser.cc; sourceTree = "<group>"; }; + 2F904214F0F0BA780D8DC4C9 /* dev_tools_client.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dev_tools_client.cc; sourceTree = "<group>"; }; 331B93A90F3BF2B9008B1C46 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 331B93AB0F3BF2DA008B1C46 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; 3380A6B50F2E9252004EF74F /* render_thread_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = render_thread_unittest.cc; sourceTree = "<group>"; }; @@ -2545,6 +2550,7 @@ 759B3A1B81E261598122B03B /* v8_unit_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = v8_unit_test.cc; sourceTree = "<group>"; }; 778D7927798B7E3FAA498D3D /* url_fetcher.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = url_fetcher.cc; sourceTree = "<group>"; }; 7849CCC221723C1BC14D6384 /* history_publisher_none.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = history_publisher_none.cc; sourceTree = "<group>"; }; + 7F10273789D2D71620792788 /* dev_tools_messages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dev_tools_messages.h; sourceTree = "<group>"; }; 8104B4AFD95DCA06B2F37551 /* chrome_paths_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chrome_paths_internal.h; sourceTree = "<group>"; }; 824FC14E0F44C56A000299E5 /* sadtab.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = sadtab.png; path = theme/sadtab.png; sourceTree = "<group>"; }; 824FC1540F44C59C000299E5 /* sad_tab_view.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = sad_tab_view.mm; sourceTree = "<group>"; }; @@ -2564,6 +2570,7 @@ 82FA32750F3A537C00271C5A /* web_contents_view_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = web_contents_view_mac.mm; path = tab_contents/web_contents_view_mac.mm; sourceTree = "<group>"; }; 82FA33440F3A7F6900271C5A /* render_widget_host_view_mac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = render_widget_host_view_mac.h; path = renderer_host/render_widget_host_view_mac.h; sourceTree = "<group>"; }; 82FA33450F3A7F6900271C5A /* render_widget_host_view_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = render_widget_host_view_mac.mm; path = renderer_host/render_widget_host_view_mac.mm; sourceTree = "<group>"; }; + 839AD6DF3CB6649E84A4A94E /* dev_tools_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dev_tools_client.h; sourceTree = "<group>"; }; 844EA0720F3E0BC900B0EF26 /* debugger_host.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = debugger_host.h; path = debugger/debugger_host.h; sourceTree = "<group>"; }; 844EA0730F3E0BEA00B0EF26 /* debugger_contents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = debugger_contents.h; path = debugger/debugger_contents.h; sourceTree = "<group>"; }; 844EA0740F3E0C1000B0EF26 /* debugger_contents.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = debugger_contents.cc; path = debugger/debugger_contents.cc; sourceTree = "<group>"; }; @@ -2744,6 +2751,7 @@ CAA0BC4B0F54A8F7004DEE42 /* hunspell.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = hunspell.xcodeproj; path = chrome/third_party/hunspell/hunspell.xcodeproj; sourceTree = "<group>"; }; D3C3DAA911D390A33D06B0B0 /* history_url_provider.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = history_url_provider.cc; path = browser/autocomplete/history_url_provider.cc; sourceTree = SOURCE_ROOT; }; D74DA6A9031CAE292790BD5E /* file_descriptor_set_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_descriptor_set_unittest.cc; sourceTree = "<group>"; }; + D792830F807C366EAB752D69 /* dev_tools_agent.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dev_tools_agent.cc; sourceTree = "<group>"; }; D941DBEFD8B8B537DE8A4DAE /* bookmark_storage.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bookmark_storage.cc; path = bookmarks/bookmark_storage.cc; sourceTree = "<group>"; }; E40CC5E10F2E348900708647 /* history_contents_provider.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = history_contents_provider.cc; path = autocomplete/history_contents_provider.cc; sourceTree = "<group>"; }; E40CC5E20F2E348900708647 /* history_contents_provider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = history_contents_provider.h; path = autocomplete/history_contents_provider.h; sourceTree = "<group>"; }; @@ -3227,6 +3235,12 @@ 4D640CC00EAE868600EBCFC0 /* chrome_plugin_host.h */, 4D640CC10EAE868600EBCFC0 /* debug_message_handler.cc */, 4D640CC20EAE868600EBCFC0 /* debug_message_handler.h */, + D792830F807C366EAB752D69 /* dev_tools_agent.cc */, + 07FE4EE1A3A0636A63757967 /* dev_tools_agent.h */, + 2F904214F0F0BA780D8DC4C9 /* dev_tools_client.cc */, + 839AD6DF3CB6649E84A4A94E /* dev_tools_client.h */, + 7F10273789D2D71620792788 /* dev_tools_messages.h */, + 0DF4243691A34E9B11373400 /* dev_tools_messages_internal.h */, 4D640CC30EAE868600EBCFC0 /* dom_ui_bindings.cc */, 4D640CC40EAE868600EBCFC0 /* dom_ui_bindings.h */, 4D640CC50EAE868600EBCFC0 /* external_host_bindings.cc */, @@ -5609,6 +5623,8 @@ 3380A69B0F2E91AE004EF74F /* child_process.cc in Sources */, 3380A69F0F2E91E5004EF74F /* chrome_plugin_lib.cc in Sources */, AB8963010F4E0907009CFFAC /* data_source_impl.cc in Sources */, + 3569E82DB055CE4B8E329CCC /* dev_tools_agent.cc in Sources */, + 29D0CE7BEF15AE6D5233BA6A /* dev_tools_client.cc in Sources */, E45076D90F1538E4003BE099 /* dom_automation_controller.cc in Sources */, E45076C90F1537F5003BE099 /* dom_ui_bindings.cc in Sources */, E45076CB0F15380C003BE099 /* external_host_bindings.cc in Sources */, 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> |