diff options
author | yurys@google.com <yurys@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-18 16:17:21 +0000 |
---|---|---|
committer | yurys@google.com <yurys@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-18 16:17:21 +0000 |
commit | 68b4d89935563f7009074cef5b7be8e0d8148bd4 (patch) | |
tree | f987689e2cc300230538482e7fa7b61b8dabd4bf | |
parent | daeb1b6db0ddff328b2ed4bc839a9f15936c3496 (diff) | |
download | chromium_src-68b4d89935563f7009074cef5b7be8e0d8148bd4.zip chromium_src-68b4d89935563f7009074cef5b7be8e0d8148bd4.tar.gz chromium_src-68b4d89935563f7009074cef5b7be8e0d8148bd4.tar.bz2 |
Create communication channel between developer tools UI implemented in JS and residing in a process different from inspected page renderer process. There is no direct IPC channel between the two processes so all messages are routed through browser process.
On the side of inspected page there is ToolsAgent existing in all renderers so that we can start inspecting the page at any moment by talking to this object.
On the side of developer tools renderer there is ToolsClient which is created only for RenderView that host developer tools UI.
This change is a slightly modified version of http://codereview.chromium.org/20221/show
Review URL: http://codereview.chromium.org/20430
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9944 0039d316-1c4b-4281-b951-d872f2087c98
27 files changed, 1019 insertions, 2 deletions
diff --git a/chrome/browser/debugger/debugger.scons b/chrome/browser/debugger/debugger.scons index 30d1a65..f34a8f1 100644 --- a/chrome/browser/debugger/debugger.scons +++ b/chrome/browser/debugger/debugger.scons @@ -54,6 +54,12 @@ input_files = ChromeFileList([ 'debugger_window.h', 'debugger_wrapper.cc', 'debugger_wrapper.h', + 'tools_contents.cc', + 'tools_contents.h', + 'tools_view.cc', + 'tools_view.h', + 'tools_window.cc', + 'tools_window.h', ]) if env.Bit('linux'): @@ -62,6 +68,9 @@ if env.Bit('linux'): 'debugger_contents.cc', 'debugger_view.cc', 'debugger_window.cc', + 'tools_contents.cc', + 'tools_view.cc', + 'tools_window.cc', ) if env.Bit('mac'): @@ -72,6 +81,9 @@ if env.Bit('mac'): 'debugger_node.cc', 'debugger_view.cc', 'debugger_window.cc', + 'tools_contents.cc', + 'tools_view.cc', + 'tools_window.cc', ) if not env.Bit('mac'): diff --git a/chrome/browser/debugger/debugger.vcproj b/chrome/browser/debugger/debugger.vcproj index d72b86a..e02dd18 100644 --- a/chrome/browser/debugger/debugger.vcproj +++ b/chrome/browser/debugger/debugger.vcproj @@ -213,6 +213,30 @@ RelativePath=".\debugger_wrapper.h" > </File> + <File + RelativePath=".\tools_contents.cc" + > + </File> + <File + RelativePath=".\tools_contents.h" + > + </File> + <File + RelativePath=".\tools_view.cc" + > + </File> + <File + RelativePath=".\tools_view.h" + > + </File> + <File + RelativePath=".\tools_window.cc" + > + </File> + <File + RelativePath=".\tools_window.h" + > + </File> </Files> <Globals> </Globals> diff --git a/chrome/browser/debugger/tools_contents.cc b/chrome/browser/debugger/tools_contents.cc new file mode 100644 index 0000000..b76913c --- /dev/null +++ b/chrome/browser/debugger/tools_contents.cc @@ -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.
+
+#include "chrome/browser/debugger/tools_contents.h"
+
+#include "base/singleton.h"
+
+ToolsContents::ToolsContents(Profile* profile, SiteInstance* instance)
+ : WebContents(profile,
+ instance,
+ NULL,
+ MSG_ROUTING_NONE,
+ NULL) {
+ set_type(TAB_CONTENTS_TOOLS);
+}
+
+void ToolsContents::RendererCreated(RenderViewHost* render_view_host) {
+ std::pair<int, int>* render_view_info =
+ ToolsContents::GetInspectedViewInfoAccessor()->GetProperty(
+ property_bag());
+ DCHECK(render_view_info);
+ if (!render_view_info)
+ return;
+
+ render_view_host->SetUpToolsClient(render_view_info->first,
+ render_view_info->second);
+ ToolsContents::GetInspectedViewInfoAccessor()->DeleteProperty(property_bag());
+}
+
+// static
+bool ToolsContents::IsToolsUrl(const GURL& url) {
+ // TODO(yurys): implement
+ return (url.SchemeIs("chrome-ui") && url.host() == "inspector" &&
+ url.path() == "/debugger-oop.html");
+}
+
+// static
+PropertyAccessor<std::pair<int, int> >*
+ ToolsContents::GetInspectedViewInfoAccessor() {
+ return Singleton<PropertyAccessor<std::pair<int, int> > >().get();
+}
+
diff --git a/chrome/browser/debugger/tools_contents.h b/chrome/browser/debugger/tools_contents.h new file mode 100644 index 0000000..9a9743d --- /dev/null +++ b/chrome/browser/debugger/tools_contents.h @@ -0,0 +1,39 @@ +// 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_BROWSER_DEBUGGER_TOOLS_CONTENTS_H_
+#define CHROME_BROWSER_DEBUGGER_TOOLS_CONTENTS_H_
+
+#include <utility>
+
+#include "chrome/browser/tab_contents/web_contents.h"
+#include "chrome/common/property_bag.h"
+
+// TODO(yurys): it may be made into DOMUI if the latter supports RendererCreated
+// notification.
+class ToolsContents : public WebContents {
+ public:
+ ToolsContents(Profile* profile, SiteInstance* instance);
+
+ static bool IsToolsUrl(const GURL& url);
+
+ // (render process id, render view id)
+ static PropertyAccessor<std::pair<int, int> >* GetInspectedViewInfoAccessor();
+
+ protected:
+ // WebContents overrides:
+ // We override updating history with a no-op so these pages
+ // are not saved to history.
+ virtual void UpdateHistoryForNavigation(const GURL& url,
+ const ViewHostMsg_FrameNavigate_Params& params) { }
+
+ // Will notify just created renderer that it's going to host developer
+ // tools UI.
+ virtual void RendererCreated(RenderViewHost* render_view_host);
+
+ DISALLOW_COPY_AND_ASSIGN(ToolsContents);
+};
+
+#endif // CHROME_BROWSER_DEBUGGER_TOOLS_CONTENTS_H_
+
diff --git a/chrome/browser/debugger/tools_view.cc b/chrome/browser/debugger/tools_view.cc new file mode 100644 index 0000000..3281029 --- /dev/null +++ b/chrome/browser/debugger/tools_view.cc @@ -0,0 +1,92 @@ +// 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/tools_view.h"
+
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/debugger/tools_contents.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/tab_contents/web_contents.h"
+#include "chrome/browser/views/tab_contents_container_view.h"
+#include "chrome/common/property_bag.h"
+#include "chrome/common/render_messages.h"
+
+ToolsView::ToolsView(int inspected_process_id, int inspected_view_id)
+ : inspected_process_id_(inspected_process_id),
+ inspected_view_id_(inspected_view_id),
+ web_contents_(NULL) {
+ web_container_ = new TabContentsContainerView();
+ AddChildView(web_container_);
+}
+
+ToolsView::~ToolsView() {
+}
+
+void ToolsView::SendToolsClientMessage(int tools_message_type,
+ const std::wstring& body) {
+ if (!web_contents_) {
+ NOTREACHED();
+ return;
+ }
+ int routing_id = web_contents_->render_view_host()->routing_id();
+ web_contents_->render_view_host()->Send(
+ new ViewMsg_ToolsClientMsg(routing_id, tools_message_type, body));
+}
+
+std::string ToolsView::GetClassName() const {
+ return "ToolsView";
+}
+
+gfx::Size ToolsView::GetPreferredSize() {
+ return gfx::Size(700, 400);
+}
+
+void ToolsView::Layout() {
+ web_container_->SetBounds(0, 0, width(), height());
+}
+
+void ToolsView::ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child) {
+ if (is_add && child == this) {
+ DCHECK(GetWidget());
+ Init();
+ }
+}
+
+void ToolsView::Init() {
+ // We can't create the WebContents until we've actually been put into a real
+ // view hierarchy somewhere.
+ Profile* profile = BrowserList::GetLastActive()->profile();
+
+ TabContents* tc = TabContents::CreateWithType(TAB_CONTENTS_TOOLS, profile,
+ NULL);
+ web_contents_ = tc->AsWebContents();
+ web_contents_->SetupController(profile);
+ web_contents_->set_delegate(this);
+ web_container_->SetTabContents(web_contents_);
+ web_contents_->render_view_host()->AllowDOMUIBindings();
+
+ ToolsContents::GetInspectedViewInfoAccessor()->SetProperty(
+ web_contents_->property_bag(),
+ std::pair<int, int>(inspected_process_id_, inspected_view_id_));
+
+ GURL contents("chrome-ui://inspector/debugger-oop.html");
+ // this will call CreateRenderView to create renderer process
+ web_contents_->controller()->LoadURL(contents, GURL(),
+ PageTransition::START_PAGE);
+}
+
+void ToolsView::OnWindowClosing() {
+ web_container_->SetTabContents(NULL); // detach last (and only) tab
+ web_contents_->CloseContents(); // destroy the tab and navigation controller
+}
+
+void ToolsView::OpenURLFromTab(TabContents* source,
+ const GURL& url, const GURL& referrer,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition) {
+ NOTREACHED();
+}
+
diff --git a/chrome/browser/debugger/tools_view.h b/chrome/browser/debugger/tools_view.h new file mode 100644 index 0000000..8d26267 --- /dev/null +++ b/chrome/browser/debugger/tools_view.h @@ -0,0 +1,75 @@ +// 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_BROWSER_DEBUGGER_TOOLS_VIEW_H_
+#define CHROME_BROWSER_DEBUGGER_TOOLS_VIEW_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/gfx/size.h"
+#include "chrome/browser/tab_contents/tab_contents_delegate.h"
+#include "chrome/views/view.h"
+
+class TabContentsContainerView;
+class WebContents;
+
+class ToolsView : public views::View,
+ public TabContentsDelegate {
+ public:
+ explicit ToolsView(int inspected_process_id, int inspected_view_id);
+ virtual ~ToolsView();
+
+ void SendToolsClientMessage(int tools_message_type, const std::wstring& body);
+
+ // Destroy content views when the window is closing.
+ void OnWindowClosing();
+
+ private:
+ // Overridden from TabContentsDelegate:
+ virtual void NavigationStateChanged(const TabContents* source,
+ unsigned changed_flags) {}
+ virtual void ReplaceContents(TabContents* source,
+ TabContents* new_contents) {}
+ virtual void AddNewContents(TabContents* source,
+ TabContents* new_contents,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_pos,
+ bool user_gesture) {}
+ virtual void ActivateContents(TabContents* contents) {}
+ virtual void LoadingStateChanged(TabContents* source) {}
+ virtual void CloseContents(TabContents* source) {}
+ virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {}
+ virtual bool IsPopup(TabContents* source) { return false; }
+ virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
+ virtual void URLStarredChanged(TabContents* source, bool) {}
+ virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
+ virtual bool CanBlur() const { return false; }
+ // Opens a new URL inside the passed in TabContents, if source is 0 open
+ // in the current front-most tab.
+ virtual void OpenURLFromTab(TabContents* source,
+ const GURL& url, const GURL& referrer,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition);
+
+ // Overridden from views::View:
+ virtual std::string GetClassName() const;
+ virtual gfx::Size GetPreferredSize();
+ virtual void Layout();
+ virtual void ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child);
+
+ void Init();
+
+ const int inspected_process_id_;
+ const int inspected_view_id_;
+ WebContents* web_contents_;
+ TabContentsContainerView* web_container_;
+
+ DISALLOW_COPY_AND_ASSIGN(ToolsView);
+};
+
+#endif // CHROME_BROWSER_DEBUGGER_TOOLS_VIEW_H_
+
diff --git a/chrome/browser/debugger/tools_window.cc b/chrome/browser/debugger/tools_window.cc new file mode 100644 index 0000000..19c602fb --- /dev/null +++ b/chrome/browser/debugger/tools_window.cc @@ -0,0 +1,54 @@ +// 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/tools_window.h"
+
+#include "chrome/browser/debugger/tools_view.h"
+#include "chrome/views/window.h"
+
+ToolsWindow::ToolsWindow() : window_(NULL), tools_view_(NULL) {
+}
+
+ToolsWindow::~ToolsWindow() {
+}
+
+void ToolsWindow::Show(int inspected_process_id,
+ int inspected_view_id) {
+ if (window_) {
+ window_->Show();
+ return;
+ }
+
+ tools_view_ = new ToolsView(inspected_process_id, inspected_view_id);
+ window_ = views::Window::CreateChromeWindow(NULL, gfx::Rect(), this);
+ window_->Show();
+}
+
+void ToolsWindow::SendToolsClientMessage(int tools_message_type,
+ const std::wstring& body) {
+ if (!tools_view_)
+ return;
+ tools_view_->SendToolsClientMessage(tools_message_type, body);
+}
+
+std::wstring ToolsWindow::GetWindowTitle() const {
+ return L"Developer Tools";
+}
+
+void ToolsWindow::WindowClosing() {
+ if (tools_view_) {
+ tools_view_->OnWindowClosing();
+ tools_view_ = NULL;
+ window_ = NULL;
+ }
+}
+
+bool ToolsWindow::CanResize() const {
+ return true;
+}
+
+views::View* ToolsWindow::GetContentsView() {
+ return tools_view_;
+}
+
diff --git a/chrome/browser/debugger/tools_window.h b/chrome/browser/debugger/tools_window.h new file mode 100644 index 0000000..738ec38 --- /dev/null +++ b/chrome/browser/debugger/tools_window.h @@ -0,0 +1,67 @@ +// 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_BROWSER_DEBUGGER_TOOLS_WINDOW_H_
+#define CHROME_BROWSER_DEBUGGER_TOOLS_WINDOW_H_
+
+#include "base/basictypes.h"
+
+// TODO(yurys): port to other platforms
+#if defined(OS_WIN)
+
+#include "chrome/views/window_delegate.h"
+
+namespace views {
+class Window;
+}
+class ToolsView;
+class TabContents;
+
+class ToolsWindow : public views::WindowDelegate {
+ public:
+ ToolsWindow();
+ virtual ~ToolsWindow();
+
+ // Show inspector window for the tab
+ void Show(int inspected_process_id,
+ int inspected_view_id);
+
+ void SendToolsClientMessage(int tools_message_type,
+ const std::wstring& body);
+
+ private:
+ // views::WindowDelegate methods:
+ virtual std::wstring GetWindowTitle() const;
+ virtual void WindowClosing();
+ virtual bool CanResize() const;
+ virtual views::View* GetContentsView();
+
+ views::Window* window_;
+ ToolsView* tools_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(ToolsWindow);
+};
+
+#else // defined(OS_WIN)
+
+class ToolsWindow {
+ public:
+ ToolsWindow() {}
+ virtual ~ToolsWindow() {}
+
+ // Show inspector window for the tab
+ void Show(int inspected_process_id,
+ int inspected_view_id) {}
+
+ void SendToolsClientMessage(int tools_message_type,
+ const std::wstring& body) {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ToolsWindow);
+};
+
+#endif // OS_WIN
+
+#endif // CHROME_BROWSER_DEBUGGER_TOOLS_WINDOW_H_
+
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index 8c64d5f..3629350 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -14,6 +14,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/cross_site_request_manager.h" #include "chrome/browser/debugger/debugger_wrapper.h" +#include "chrome/browser/debugger/tools_window.h" #include "chrome/browser/profile.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/renderer_host/renderer_security_policy.h" @@ -87,6 +88,7 @@ RenderViewHost::RenderViewHost(SiteInstance* instance, renderer_initialized_(false), waiting_for_drag_context_response_(false), debugger_attached_(false), + tools_window_(NULL), enable_dom_ui_bindings_(false), pending_request_id_(0), enable_external_host_bindings_(false), @@ -96,7 +98,9 @@ RenderViewHost::RenderViewHost(SiteInstance* instance, run_modal_reply_msg_(NULL), has_unload_listener_(false), is_waiting_for_unload_ack_(false), - are_javascript_messages_suppressed_(false) { + are_javascript_messages_suppressed_(false), + inspected_process_id_(0), + inspected_view_id_(0) { DCHECK(instance_); DCHECK(delegate_); if (modal_dialog_event == NULL) @@ -554,6 +558,12 @@ void RenderViewHost::ShowJavaScriptConsole() { Send(new ViewMsg_ShowJavaScriptConsole(routing_id())); } +void RenderViewHost::ShowDeveloperTools() { + if (!tools_window_.get()) + tools_window_.reset(new ToolsWindow); + tools_window_->Show(process()->host_id(), routing_id()); +} + void RenderViewHost::DragSourceEndedAt( int client_x, int client_y, int screen_x, int screen_y) { Send(new ViewMsg_DragSourceEndedOrMoved( @@ -582,6 +592,16 @@ void RenderViewHost::AllowDOMUIBindings() { process()->host_id()); } +void RenderViewHost::SetUpToolsClient(int inspected_process_id, + int inspected_view_id) { + RendererSecurityPolicy::GetInstance()->GrantDOMUIBindings( + process()->host_id()); + Send(new ViewMsg_SetUpToolsClient(routing_id())); + + inspected_process_id_ = inspected_process_id; + inspected_view_id_ = inspected_view_id; +} + void RenderViewHost::AllowExternalHostBindings() { enable_external_host_bindings_ = true; } @@ -732,6 +752,8 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(ViewHostMsg_AddMessageToConsole, OnAddMessageToConsole) IPC_MESSAGE_HANDLER(ViewHostMsg_DebuggerOutput, OnDebuggerOutput); IPC_MESSAGE_HANDLER(ViewHostMsg_DidDebugAttach, DidDebugAttach); + IPC_MESSAGE_HANDLER(ViewHostMsg_ToolsAgentMsg, OnToolsAgentMsg); + IPC_MESSAGE_HANDLER(ViewHostMsg_ToolsClientMsg, OnToolsClientMsg); IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction, OnUserMetricsRecordAction) IPC_MESSAGE_HANDLER(ViewHostMsg_MissingPluginStatus, OnMissingPluginStatus); @@ -1171,6 +1193,26 @@ void RenderViewHost::DidDebugAttach() { } } +void RenderViewHost::OnToolsAgentMsg(int tools_message_type, + const std::wstring& body) { + RenderViewHost* host = RenderViewHost::FromID(inspected_process_id_, + inspected_view_id_); + CHECK(host); + if (host) { + host->Send(new ViewMsg_ToolsAgentMsg( + inspected_view_id_, tools_message_type, body)); + } +} + +void RenderViewHost::OnToolsClientMsg(int tools_message_type, + const std::wstring& body) { + if (!tools_window_.get()) { + NOTREACHED(); + return; + } + tools_window_->SendToolsClientMessage(tools_message_type, body); +} + void RenderViewHost::OnUserMetricsRecordAction(const std::wstring& action) { UserMetrics::RecordComputedAction(action.c_str(), process()->profile()); } diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index 2f36219..dbd18a1 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -26,6 +26,7 @@ class NavigationEntry; class RenderViewHostDelegate; class SiteInstance; class SkBitmap; +class ToolsWindow; class ViewMsg_Navigate; struct ContextMenuParams; struct ViewHostMsg_DidPrintPage_Params; @@ -291,6 +292,9 @@ class RenderViewHost : public RenderWidgetHost { // Show the JavaScript console. void ShowJavaScriptConsole(); + // Show the Web Inspector. + void ShowDeveloperTools(); + // Notifies the renderer that a drop occurred. This is necessary because the // render may be the one that started the drag. void DragSourceEndedAt( @@ -320,6 +324,11 @@ class RenderViewHost : public RenderWidgetHost { // Must be called before CreateRenderView(). void AllowDOMUIBindings(); + // Tell the render view to connect as a tools client to the specified + // renderer. Must be called when RenderView is created but before any + // navigation. + void SetUpToolsClient(int inspected_process_id, int inspected_view_id); + // Sets a property with the given name and value on the DOM UI binding object. // Must call AllowDOMUIBindings() on this renderer first. void SetDOMUIProperty(const std::string& name, const std::string& value); @@ -506,6 +515,8 @@ class RenderViewHost : public RenderWidgetHost { const std::wstring& source_id); void OnDebuggerOutput(const std::wstring& output); void DidDebugAttach(); + void OnToolsAgentMsg(int tools_message_type, const std::wstring& body); + void OnToolsClientMsg(int tools_message_type, const std::wstring& body); void OnUserMetricsRecordAction(const std::wstring& action); void OnMissingPluginStatus(int status); void OnMessageReceived(IPC::Message* msg) { } @@ -561,9 +572,12 @@ class RenderViewHost : public RenderWidgetHost { // information. bool waiting_for_drag_context_response_; - // is the debugger attached to us or not + // If the debugger attached to us or not. bool debugger_attached_; + // Allows to show exactly one developer tools window for this render view. + scoped_ptr<ToolsWindow> tools_window_; + // True if we've been told to set up the the Javascript bindings for // sending messages back to the browser. bool enable_dom_ui_bindings_; @@ -610,6 +624,10 @@ class RenderViewHost : public RenderWidgetHost { bool are_javascript_messages_suppressed_; + int inspected_process_id_; + + int inspected_view_id_; + DISALLOW_EVIL_CONSTRUCTORS(RenderViewHost); }; diff --git a/chrome/browser/tab_contents/tab_contents_factory.cc b/chrome/browser/tab_contents/tab_contents_factory.cc index 18f3569..64f0605 100644 --- a/chrome/browser/tab_contents/tab_contents_factory.cc +++ b/chrome/browser/tab_contents/tab_contents_factory.cc @@ -11,6 +11,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/debugger/debugger_contents.h" +#include "chrome/browser/debugger/tools_contents.h" #include "chrome/browser/tab_contents/native_ui_contents.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_factory.h" @@ -61,6 +62,9 @@ TabContents* TabContents::CreateWithType(TabContentsType type, case TAB_CONTENTS_DEBUGGER: contents = new DebuggerContents(profile, instance); break; + case TAB_CONTENTS_TOOLS: + contents = new ToolsContents(profile, instance); + break; case TAB_CONTENTS_DOM_UI: contents = new DOMUIContents(profile, instance, NULL); break; @@ -108,6 +112,9 @@ TabContentsType TabContents::TypeForURL(GURL* url) { if (DebuggerContents::IsDebuggerUrl(*url)) return TAB_CONTENTS_DEBUGGER; + if (ToolsContents::IsToolsUrl(*url)) + return TAB_CONTENTS_TOOLS; + if (url->SchemeIs(DOMUIContents::GetScheme().c_str())) return TAB_CONTENTS_DOM_UI; diff --git a/chrome/browser/tab_contents/tab_contents_type.h b/chrome/browser/tab_contents/tab_contents_type.h index 87cd6452..6a8afd9 100644 --- a/chrome/browser/tab_contents/tab_contents_type.h +++ b/chrome/browser/tab_contents/tab_contents_type.h @@ -21,6 +21,7 @@ enum TabContentsType { TAB_CONTENTS_ABOUT_UI, TAB_CONTENTS_DEBUGGER, TAB_CONTENTS_DOM_UI, + TAB_CONTENTS_TOOLS, TAB_CONTENTS_NUM_TYPES }; diff --git a/chrome/chrome.xcodeproj/project.pbxproj b/chrome/chrome.xcodeproj/project.pbxproj index daa33e87..d1af5e8 100644 --- a/chrome/chrome.xcodeproj/project.pbxproj +++ b/chrome/chrome.xcodeproj/project.pbxproj @@ -293,6 +293,7 @@ 8570EB3F140C07ABF1957F12 /* url_pattern_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = A9C335E39D39A7DE087850FC /* url_pattern_unittest.cc */; }; 85C8A66BBC97243AF1C11166 /* gears_integration.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D7BF8830E9D4839009A6919 /* gears_integration.cc */; }; 8CB218DCFAC761AC876C6531 /* ssl_blocking_page.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5D16ECB0F21451600861FAC /* ssl_blocking_page.cc */; }; + 8BFCF870135974131607BE96 /* tools_client.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5F14A0FCE27716C1320910BF /* tools_client.cc */; }; 8F51B73AAAF1772ECF9BD180 /* url_fetcher.cc in Sources */ = {isa = PBXBuildFile; fileRef = 778D7927798B7E3FAA498D3D /* url_fetcher.cc */; }; 9084D27A4F8690E6FD31083B /* session_backend.cc in Sources */ = {isa = PBXBuildFile; fileRef = 35AC9D9A03545594C102C5C1 /* session_backend.cc */; }; 94542322A5E5A8F4FDDAB7F0 /* render_view_host_manager.cc in Sources */ = {isa = PBXBuildFile; fileRef = A76E42AD0F28EDB5009A7E88 /* render_view_host_manager.cc */; }; @@ -362,6 +363,7 @@ BAC2B7A80F43595A0063A33E /* resource_dispatcher_host_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = BAC2B7A70F43594A0063A33E /* resource_dispatcher_host_unittest.cc */; }; BAC2B8AD0F436C7F0063A33E /* cross_site_resource_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = A7C613DC0F30D886008CEE5D /* cross_site_resource_handler.cc */; }; BADB8B710F3A35AC00989B26 /* resource_dispatcher_host.cc in Sources */ = {isa = PBXBuildFile; fileRef = BADB8B6D0F3A356000989B26 /* resource_dispatcher_host.cc */; }; + C3264B8F815F3A647E588B3B /* tools_agent.cc in Sources */ = {isa = PBXBuildFile; fileRef = CC4B6C6003DFDA919DF82F03 /* tools_agent.cc */; }; C53EBF7E1E204C3780FD4A7D /* ssl_policy.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5D16ED10F21451600861FAC /* ssl_policy.cc */; }; C6C256C56BA114D53849523F /* greasemonkey_api_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1F43A7C85092C58AAF011F78 /* greasemonkey_api_unittest.cc */; }; C8F5EB819EA38CE9D50AF5B5 /* history.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D7BF9EC0E9D48F7009A6919 /* history.cc */; }; @@ -2405,6 +2407,9 @@ 4F9429998AC2703984BAB828 /* resolve_proxy_msg_helper.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = resolve_proxy_msg_helper.cc; sourceTree = "<group>"; }; 534E66C30F311BEC0006B2B2 /* temp_scaffolding_stubs.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = temp_scaffolding_stubs.cc; sourceTree = "<group>"; }; 56E1D7DF17D327BFCB0B895D /* test_web_contents.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = test_web_contents.cc; path = tab_contents/test_web_contents.cc; sourceTree = "<group>"; }; + 5EEF2C2CF0433472C652E800 /* tools_agent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tools_agent.h; sourceTree = "<group>"; }; + 5EEF8662A1B4ABE060426953 /* tools_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tools_client.h; sourceTree = "<group>"; }; + 5F14A0FCE27716C1320910BF /* tools_client.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tools_client.cc; sourceTree = "<group>"; }; 629BF493DEA096E2DD844F2B /* autofill_manager.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = autofill_manager.cc; sourceTree = "<group>"; }; 6447F24FADC63E58A44DB762 /* url_pattern.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = url_pattern.cc; path = extensions/url_pattern.cc; sourceTree = "<group>"; }; 699499C4FBA07FB2D7B298A2 /* user_script.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = user_script.cc; path = extensions/user_script.cc; sourceTree = "<group>"; }; @@ -2596,6 +2601,8 @@ C18F2A0A6FB6BEF75406511D /* chrome_paths_mac.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = chrome_paths_mac.cc; sourceTree = "<group>"; }; C3F9577C67188A5A4E3A6E41 /* session_restore.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = session_restore.cc; path = sessions/session_restore.cc; sourceTree = "<group>"; }; C8D26D9EC81E03E91E270463 /* session_service.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = session_service.cc; path = sessions/session_service.cc; sourceTree = "<group>"; }; + CC4B6C6003DFDA919DF82F03 /* tools_agent.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tools_agent.cc; sourceTree = "<group>"; }; + CEEB8E8A0729671812756F11 /* tools_messages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tools_messages.h; sourceTree = "<group>"; }; D74DA6A9031CAE292790BD5E /* file_descriptor_set_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_descriptor_set_unittest.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>"; }; @@ -3051,6 +3058,11 @@ B51F6D120F37C4DC00152D66 /* renderer_main_platform_delegate_win.cc */, B5D030EF0F3A3C43001238AB /* renderer_main_unittest.cc */, 4D640CDA0EAE868600EBCFC0 /* renderer_resources.h */, + CC4B6C6003DFDA919DF82F03 /* tools_agent.cc */, + 5EEF2C2CF0433472C652E800 /* tools_agent.h */, + 5F14A0FCE27716C1320910BF /* tools_client.cc */, + 5EEF8662A1B4ABE060426953 /* tools_client.h */, + CEEB8E8A0729671812756F11 /* tools_messages.h */, 4D640CC90EAE868600EBCFC0 /* user_script_slave.cc */, 4D640CCA0EAE868600EBCFC0 /* user_script_slave.h */, 4D640CDC0EAE868600EBCFC0 /* visitedlink_slave.cc */, @@ -5335,6 +5347,8 @@ 3380A6A10F2E91F9004EF74F /* render_process.cc in Sources */, 3380A69D0F2E91D4004EF74F /* render_thread.cc in Sources */, A7A20E650F3A1E1C00F62B4D /* render_view.cc in Sources */, + C3264B8F815F3A647E588B3B /* tools_agent.cc in Sources */, + 8BFCF870135974131607BE96 /* tools_client.cc in Sources */, B503E0F00F0175FD00547DC6 /* user_script_slave.cc in Sources */, B51F6D2E0F37D04200152D66 /* renderer_main.cc in Sources */, B51F6D150F37C4DC00152D66 /* renderer_main_platform_delegate_mac.mm in Sources */, diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index a8adb2f..1fa3650 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -11,6 +11,7 @@ #include "base/command_line.h" #include "base/gfx/png_encoder.h" #include "base/gfx/native_widget_types.h" +#include "base/process_util.h" #include "base/string_piece.h" #include "base/string_util.h" #include "build/build_config.h" @@ -25,6 +26,7 @@ #include "chrome/common/thumbnail_score.h" #include "chrome/renderer/about_handler.h" #include "chrome/renderer/debug_message_handler.h" +#include "chrome/renderer/tools_client.h" #include "chrome/renderer/localized_error.h" #include "chrome/renderer/render_process.h" #include "chrome/renderer/user_script_slave.h" @@ -168,6 +170,9 @@ RenderView::RenderView(RenderThreadBase* render_thread) method_factory_(this), first_default_plugin_(NULL), printed_document_width_(0), + tools_agent_(NULL), + enable_tools_client_(false), + tools_client_(NULL), history_back_list_count_(0), history_forward_list_count_(0), disable_popup_blocking_(false), @@ -196,6 +201,10 @@ RenderView::~RenderView() { } render_thread_->RemoveFilter(debug_message_handler_); + render_thread_->RemoveFilter(tools_agent_); + if (tools_client_.get()) { + render_thread_->RemoveFilter(tools_client_); + } #ifdef CHROME_PERSONALIZATION Personalization::CleanupRendererPersonalization(personalization_); @@ -313,6 +322,9 @@ void RenderView::Init(gfx::NativeViewId parent_hwnd, debug_message_handler_ = new DebugMessageHandler(this); render_thread_->AddFilter(debug_message_handler_); + + tools_agent_ = new ToolsAgent(this); + render_thread_->AddFilter(tools_agent_); } void RenderView::OnMessageReceived(const IPC::Message& message) { @@ -355,6 +367,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_SetUpToolsClient, OnSetUpToolsClient) IPC_MESSAGE_HANDLER(ViewMsg_DownloadImage, OnDownloadImage) IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest) IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole) @@ -897,6 +910,10 @@ void RenderView::OnShowJavaScriptConsole() { webview()->ShowJavaScriptConsole(); } +void RenderView::OnSetUpToolsClient() { + enable_tools_client_ = true; +} + void RenderView::OnStopFinding(bool clear_selection) { WebView* view = webview(); if (!view) @@ -1502,6 +1519,13 @@ void RenderView::BindDOMAutomationController(WebFrame* webframe) { L"domAutomationController"); } +void RenderView::CreateToolsClient() { + DCHECK(!tools_client_.get()); + tools_client_ = new ToolsClient(this); + webview()->SetUpToolsProxy(tools_client_); + render_thread_->AddFilter(tools_client_); +} + void RenderView::WindowObjectCleared(WebFrame* webframe) { external_js_object_.set_render_view(this); external_js_object_.BindToJavascript(webframe, L"external"); @@ -1517,6 +1541,11 @@ void RenderView::WindowObjectCleared(WebFrame* webframe) { external_host_bindings_.set_routing_id(routing_id_); external_host_bindings_.BindToJavascript(webframe, L"externalHost"); } + // TODO(yurys): we wouldn't need to check that tools_client_ is not set yet if + // WindowObjectCleared were not called several times recursively + if (enable_tools_client_ && !tools_client_.get()) { + CreateToolsClient(); + } #ifdef CHROME_PERSONALIZATION Personalization::ConfigureRendererPersonalization(personalization_, this, diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 6cafaa6..64e0caa 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -22,6 +22,8 @@ #include "chrome/renderer/dom_ui_bindings.h" #include "chrome/renderer/external_host_bindings.h" #include "chrome/renderer/external_js_object.h" +#include "chrome/renderer/tools_agent.h" +#include "chrome/renderer/tools_client.h" #include "chrome/renderer/render_widget.h" #include "testing/gtest/include/gtest/gtest_prod.h" #include "webkit/glue/console_message_level.h" @@ -438,6 +440,7 @@ class RenderView : public RenderWidget, void OnCopyImageAt(int x, int y); void OnInspectElement(int x, int y); void OnShowJavaScriptConsole(); + void OnSetUpToolsClient(); void OnCancelDownload(int32 download_id); void OnFind(const FindInPageRequest& request); void OnZoom(int function); @@ -551,6 +554,10 @@ class RenderView : public RenderWidget, // information to the browser process. void BindDOMAutomationController(WebFrame* webframe); + // Creates ToolsClient and sets up JavaScript bindings for developer tools UI + // that is going to be hosted by this RenderView. + void CreateToolsClient(); + void set_opened_by_user_gesture(bool value) { opened_by_user_gesture_ = value; } @@ -693,6 +700,14 @@ class RenderView : public RenderWidget, scoped_refptr<DebugMessageHandler> debug_message_handler_; + // Provides access to this renderer from the remote Inspector UI. + scoped_refptr<ToolsAgent> tools_agent_; + + // Whether this renderer will serve as Inspector UI. + bool enable_tools_client_; + + scoped_refptr<ToolsClient> 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 4f5ba60..f1ed92f 100644 --- a/chrome/renderer/renderer.scons +++ b/chrome/renderer/renderer.scons @@ -79,6 +79,11 @@ input_files = ChromeFileList([ 'renderer_glue.cc', 'renderer_main.cc', 'renderer_resources.h', + 'tools_agent.cc', + 'tools_agent.h', + 'tools_client.cc', + 'tools_client.h', + 'tools_messages.h', 'user_script_slave.cc', 'user_script_slave.h', 'visitedlink_slave.cc', diff --git a/chrome/renderer/renderer.vcproj b/chrome/renderer/renderer.vcproj index 7e50f8f..8a1dc13 100644 --- a/chrome/renderer/renderer.vcproj +++ b/chrome/renderer/renderer.vcproj @@ -310,6 +310,26 @@ > </File> <File + RelativePath=".\tools_agent.cc" + > + </File> + <File + RelativePath=".\tools_agent.h" + > + </File> + <File + RelativePath=".\tools_client.cc" + > + </File> + <File + RelativePath=".\tools_client.h" + > + </File> + <File + RelativePath=".\tools_messages.h" + > + </File> + <File RelativePath=".\user_script_slave.cc" > </File> diff --git a/chrome/renderer/tools_agent.cc b/chrome/renderer/tools_agent.cc new file mode 100644 index 0000000..db622ca --- /dev/null +++ b/chrome/renderer/tools_agent.cc @@ -0,0 +1,138 @@ +// 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/tools_agent.h"
+
+#include "chrome/common/render_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"
+
+ToolsAgent::ToolsAgent(RenderView* view)
+ : debugger_(NULL),
+ view_(view),
+ view_loop_(g_render_thread->message_loop()) {
+}
+
+ToolsAgent::~ToolsAgent() {
+}
+
+void ToolsAgent::Send(ToolsClientMessageType message_type,
+ const std::wstring& body) {
+ view_->Send(new ViewHostMsg_ToolsClientMsg(
+ view_->routing_id(), message_type, body));
+}
+
+// Called on IO thread.
+bool ToolsAgent::OnMessageReceived(const IPC::Message& message) {
+ if (message.routing_id() != view_->routing_id())
+ return false;
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ToolsAgent, message)
+ IPC_MESSAGE_HANDLER(ViewMsg_ToolsAgentMsg, OnToolsAgentMsg)
+ IPC_MESSAGE_UNHANDLED(handled = false);
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+// Called on IO thread.
+void ToolsAgent::OnToolsAgentMsg(int tools_message_type,
+ const std::wstring& body) {
+ view_loop_->PostTask(FROM_HERE, NewRunnableMethod(
+ this,
+ &ToolsAgent::HandleMessageInRenderThread,
+ tools_message_type,
+ body));
+}
+
+void ToolsAgent::HandleMessageInRenderThread(
+ int tools_message_type, const std::wstring& body) {
+ DCHECK(MessageLoop::current() == view_loop_);
+
+ switch (tools_message_type) {
+ case TOOLS_AGENT_MSG_DEBUG_ATTACH:
+ OnDebugAttach();
+ break;
+ case TOOLS_AGENT_MSG_DEBUG_DETACH:
+ OnDebugDetach();
+ break;
+ case TOOLS_AGENT_MSG_DEBUG_BREAK:
+ OnDebugBreak(body == L"true");
+ break;
+ case TOOLS_AGENT_MSG_DEBUG_COMMAND:
+ OnCommand(body);
+ break;
+ default:
+ NOTREACHED() << "Unknown ToolsAgentMessageType: " << tools_message_type;
+ }
+}
+
+void ToolsAgent::DebuggerOutput(const std::wstring& out) {
+ Send(TOOLS_CLIENT_MSG_DEBUGGER_OUTPUT, out);
+}
+
+void ToolsAgent::EvaluateScript(const std::wstring& script) {
+ DCHECK(MessageLoop::current() == view_loop_);
+ // It's possible that this will get cleared out from under us.
+ view_->EvaluateScript(L"", script);
+}
+
+void ToolsAgent::OnDebugAttach() {
+ DCHECK(MessageLoop::current() == view_loop_);
+ if (!debugger_) {
+ debugger_ = new DebuggerBridge(this);
+ }
+
+ debugger_->Attach();
+
+ Send(TOOLS_CLIENT_MSG_DID_DEBUG_ATTACH, L"");
+
+// 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 ToolsAgent::OnDebugDetach() {
+ DCHECK(MessageLoop::current() == view_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 ToolsAgent::OnDebugBreak(bool force) {
+ DCHECK(MessageLoop::current() == view_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)
+ EvaluateScript(std::wstring(L"javascript:void(0)"));
+}
+
+void ToolsAgent::OnCommand(const std::wstring& cmd) {
+ DCHECK(MessageLoop::current() == view_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/tools_agent.h b/chrome/renderer/tools_agent.h new file mode 100644 index 0000000..6a4aeb6 --- /dev/null +++ b/chrome/renderer/tools_agent.h @@ -0,0 +1,67 @@ +// 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_TOOLS_AGENT_H_
+#define CHROME_RENDERER_TOOLS_AGENT_H_
+
+#include "base/basictypes.h"
+#include "base/message_loop.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "chrome/common/ipc_channel_proxy.h"
+#include "chrome/renderer/tools_messages.h"
+#include "webkit/glue/debugger_bridge.h"
+
+class Message;
+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 ToolsAgent : public IPC::ChannelProxy::MessageFilter,
+ public DebuggerBridge::Delegate {
+ public:
+ // ToolsAgent is a field of the RenderView. The view is supposed to be alive
+ // at least until OnFilterRemoved method is called.
+ explicit ToolsAgent(RenderView* view);
+ virtual ~ToolsAgent();
+
+ private:
+ // Sends message to ToolsClient.
+ void Send(ToolsClientMessageType message_type, const std::wstring& body);
+
+ // IPC::ChannelProxy::MessageFilter overrides:
+ virtual bool OnMessageReceived(const IPC::Message& message);
+
+ // Called on IO thread.
+ void OnToolsAgentMsg(int tools_message_type, const std::wstring& body);
+
+ // Message filer's OnMessageReceived method is called on IO thread while
+ // ToolsAgent messages have to be handled in render thread. This method is
+ // called in render thread to handle tools agent message.
+ void HandleMessageInRenderThread(int tools_message_type,
+ const std::wstring& body);
+
+ // 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 must be executed in render thread.
+ void OnDebugAttach();
+ void OnDebugDetach();
+ void OnDebugBreak(bool force);
+ void OnCommand(const std::wstring& cmd);
+
+ scoped_refptr<DebuggerBridge> debugger_;
+ RenderView* view_;
+ MessageLoop* view_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(ToolsAgent);
+};
+
+#endif // CHROME_RENDERER_TOOLS_AGENT_H_
+
diff --git a/chrome/renderer/tools_client.cc b/chrome/renderer/tools_client.cc new file mode 100644 index 0000000..c33e2f0 --- /dev/null +++ b/chrome/renderer/tools_client.cc @@ -0,0 +1,82 @@ +// 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/tools_client.h"
+
+#include "chrome/common/render_messages.h"
+#include "chrome/renderer/render_view.h"
+#include "webkit/glue/tools_proxy.h"
+
+ToolsClient::ToolsClient(RenderView* view)
+ : tools_ui_(NULL),
+ render_view_(view),
+ view_loop_(MessageLoop::current()) {
+}
+
+ToolsClient::~ToolsClient() {
+ tools_ui_ = NULL;
+}
+
+void ToolsClient::Send(ToolsAgentMessageType message_type,
+ const std::wstring& json_arg) {
+ render_view_->Send(new ViewHostMsg_ToolsAgentMsg(
+ render_view_->routing_id(), message_type, json_arg));
+}
+
+// IPC::ChannelProxy::MessageFilter overrides:
+bool ToolsClient::OnMessageReceived(const IPC::Message& message) {
+ if (message.routing_id() != render_view_->routing_id()) {
+ NOTREACHED();
+ return false;
+ }
+
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ToolsClient, message)
+ IPC_MESSAGE_HANDLER(ViewMsg_ToolsClientMsg, OnToolsClientMessage)
+ IPC_MESSAGE_UNHANDLED(handled = false);
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void ToolsClient::OnToolsClientMessage(int tools_message_type,
+ const std::wstring& body) {
+ view_loop_->PostTask(FROM_HERE, NewRunnableMethod(
+ this,
+ &ToolsClient::HandleMessageInRenderThread,
+ tools_message_type,
+ body));
+}
+
+void ToolsClient::HandleMessageInRenderThread(int tools_message_type,
+ const std::wstring& body) {
+ DCHECK(view_loop_ == MessageLoop::current());
+
+ switch (tools_message_type) {
+ case TOOLS_CLIENT_MSG_DID_DEBUG_ATTACH:
+ OnDidDebugAttach();
+ break;
+ default:
+ NOTREACHED() << "Unknown message type: " << tools_message_type;
+ }
+}
+
+void ToolsClient::OnDidDebugAttach() {
+ DCHECK(view_loop_ == MessageLoop::current());
+ if (tools_ui_)
+ tools_ui_->OnDidDebugAttach();
+}
+
+// DebuggerProxy methods:
+void ToolsClient::SetToolsUI(ToolsUI* tools_ui) {
+ tools_ui_ = tools_ui;
+}
+
+void ToolsClient::DebugAttach() {
+ Send(TOOLS_AGENT_MSG_DEBUG_ATTACH, L"");
+}
+
+void ToolsClient::DebugDetach() {
+ Send(TOOLS_AGENT_MSG_DEBUG_DETACH, L"");
+}
+
diff --git a/chrome/renderer/tools_client.h b/chrome/renderer/tools_client.h new file mode 100644 index 0000000..26894ae --- /dev/null +++ b/chrome/renderer/tools_client.h @@ -0,0 +1,60 @@ +// 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_TOOLS_CLIENT_H_
+#define CHROME_RENDERER_TOOLS_CLIENT_H_
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "chrome/common/ipc_channel_proxy.h"
+#include "chrome/renderer/tools_messages.h"
+#include "webkit/glue/tools_proxy.h"
+
+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 ToolsAgent object.
+class ToolsClient : public ToolsProxy,
+ public IPC::ChannelProxy::MessageFilter {
+ public:
+ explicit ToolsClient(RenderView* view);
+ virtual ~ToolsClient();
+
+ private:
+ // DebuggerProxy overrides
+ virtual void SetToolsUI(ToolsUI* tools_ui);
+ virtual void DebugAttach();
+ virtual void DebugDetach();
+
+ // All these OnXXX methods must be executed in render thread.
+ void OnDidDebugAttach();
+
+ // Sends message to ToolsAgent.
+ void Send(ToolsAgentMessageType message_type, const std::wstring& json_arg);
+
+ // IPC::ChannelProxy::MessageFilter overrides:
+ virtual bool OnMessageReceived(const IPC::Message& message);
+
+ // Called on IO thread.
+ void OnToolsClientMessage(int tools_message_type, const std::wstring& body);
+
+ // Message filer's OnMessageReceived method is called on IO thread while
+ // ToolsClient messages have to be handled in render thread. This method is
+ // called in render thread to handle tools client message.
+ void HandleMessageInRenderThread(int tools_message_type,
+ const std::wstring& body);
+
+ ToolsUI* tools_ui_;
+ RenderView* render_view_;
+ MessageLoop* view_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(ToolsClient);
+};
+
+#endif // CHROME_RENDERER_TOOLS_CLIENT_H_
+
diff --git a/chrome/renderer/tools_messages.h b/chrome/renderer/tools_messages.h new file mode 100644 index 0000000..3f6d41d --- /dev/null +++ b/chrome/renderer/tools_messages.h @@ -0,0 +1,22 @@ +// 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_TOOLS_MESSAGES_H_
+#define CHROME_RENDERER_TOOLS_MESSAGES_H_
+
+enum ToolsAgentMessageType {
+ TOOLS_AGENT_MSG_DEBUG_ATTACH = 0,
+ TOOLS_AGENT_MSG_DEBUG_BREAK,
+ TOOLS_AGENT_MSG_DEBUG_COMMAND,
+ TOOLS_AGENT_MSG_DEBUG_DETACH
+};
+
+enum ToolsClientMessageType {
+ TOOLS_CLIENT_MSG_ADD_MESSAGE_TO_CONSOLE = 0,
+ TOOLS_CLIENT_MSG_DEBUGGER_OUTPUT,
+ TOOLS_CLIENT_MSG_DID_DEBUG_ATTACH
+};
+
+#endif // CHROME_RENDERER_TOOLS_MESSAGES_H_
+
diff --git a/webkit/glue/glue.vcproj b/webkit/glue/glue.vcproj index acaad6f..1f7e9d7 100644 --- a/webkit/glue/glue.vcproj +++ b/webkit/glue/glue.vcproj @@ -173,6 +173,10 @@ > </File> <File + RelativePath=".\tools_proxy.h" + > + </File> + <File RelativePath=".\webdatasource.h" > </File> diff --git a/webkit/glue/tools_proxy.h b/webkit/glue/tools_proxy.h new file mode 100644 index 0000000..d4d70b5 --- /dev/null +++ b/webkit/glue/tools_proxy.h @@ -0,0 +1,75 @@ +// 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.
+
+// Developer tools consist of following parts:
+//
+// ToolsAgent lives in the renderer of an inspected page and provides access to
+// the pages resources, DOM, v8 etc. by means of IPC messages.
+//
+// ToolsClient is a thin delegate that lives in the tools front-end renderer and
+// converts IPC messages to frontend methods calls and allows the frontend to
+// send messages to the ToolsAgent.
+//
+// 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 <--> ToolsClient+<-- IPC -->+ (browser process) |
+// |frontend | | |
+// -------------------------- -----------+--------
+// ^
+// |
+// IPC
+// |
+// v
+// --------------------------+-------
+// | inspected page <--> ToolsAgent |
+// | |
+// | (inspected page renderer process)|
+// ----------------------------------
+//
+// This file describes interface between tools frontend and ToolsClient in the
+// above diagram.
+
+#ifndef WEBKIT_GLUE_TOOLS_PROXY_H_
+#define WEBKIT_GLUE_TOOLS_PROXY_H_
+
+#include "base/basictypes.h"
+
+class ToolsUI;
+
+// Interface for sending messages to remote ToolsAgent.
+class ToolsProxy {
+ public:
+ ToolsProxy() {}
+ virtual ~ToolsProxy() {}
+
+ virtual void SetToolsUI(ToolsUI* tools_ui) = 0;
+
+ virtual void DebugAttach() = 0;
+ virtual void DebugDetach() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ToolsProxy);
+};
+
+
+// Interface for accessing tools frontend.
+class ToolsUI {
+ public:
+ ToolsUI() {}
+ virtual ~ToolsUI() {}
+
+ virtual void OnDidDebugAttach() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ToolsUI);
+};
+
+#endif // WEBKIT_GLUE_TOOLS_PROXY_H_
+
diff --git a/webkit/glue/webview.h b/webkit/glue/webview.h index 39d608c..f0f3e26 100644 --- a/webkit/glue/webview.h +++ b/webkit/glue/webview.h @@ -12,6 +12,7 @@ #include "base/ref_counted.h" #include "webkit/glue/webwidget.h" +class ToolsProxy; struct WebDropData; struct WebPreferences; class GURL; @@ -165,6 +166,10 @@ class WebView : public WebWidget { // Show the JavaScript console. virtual void ShowJavaScriptConsole() = 0; + // Set up developer tools UI bindings. It is guaranteed that tools_proxy will + // overlive this webview. + virtual void SetUpToolsProxy(ToolsProxy* tools_proxy) = 0; + // Notifies the webview that a drag has terminated. virtual void DragSourceEndedAt( int client_x, int client_y, int screen_x, int screen_y) = 0; diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc index 7959b6f..496aa7d 100644 --- a/webkit/glue/webview_impl.cc +++ b/webkit/glue/webview_impl.cc @@ -1429,6 +1429,11 @@ void WebViewImpl::ShowJavaScriptConsole() { page_->inspectorController()->showPanel(InspectorController::ConsolePanel); } +void WebViewImpl::SetUpToolsProxy(ToolsProxy* tools_proxy) { + DCHECK(page_ != NULL); + // TODO(yurys): implement +} + void WebViewImpl::DragSourceEndedAt( int client_x, int client_y, int screen_x, int screen_y) { PlatformMouseEvent pme(IntPoint(client_x, client_y), diff --git a/webkit/glue/webview_impl.h b/webkit/glue/webview_impl.h index c511e7b..ed0dbce 100644 --- a/webkit/glue/webview_impl.h +++ b/webkit/glue/webview_impl.h @@ -37,6 +37,7 @@ class Widget; class AutocompletePopupMenuClient; class ImageResourceFetcher; class SearchableFormData; +class ToolsProxy; struct WebDropData; class WebHistoryItemImpl; class WebKeyboardEvent; @@ -89,6 +90,7 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> { virtual void CopyImageAt(int x, int y); virtual void InspectElement(int x, int y); virtual void ShowJavaScriptConsole(); + virtual void SetUpToolsProxy(ToolsProxy* tools_proxy); virtual void DragSourceEndedAt( int client_x, int client_y, int screen_x, int screen_y); virtual void DragSourceMovedTo( |