diff options
author | dgozman <dgozman@chromium.org> | 2015-03-09 06:07:57 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-09 13:08:21 +0000 |
commit | ea764811d0f4a41ef8bb9768737bc6f7dde6f27f (patch) | |
tree | d900f50ba3263671ecf1ba68efca3d9b1b42f01a | |
parent | 7999b8831356451de5559653df030f1a3acc38b7 (diff) | |
download | chromium_src-ea764811d0f4a41ef8bb9768737bc6f7dde6f27f.zip chromium_src-ea764811d0f4a41ef8bb9768737bc6f7dde6f27f.tar.gz chromium_src-ea764811d0f4a41ef8bb9768737bc6f7dde6f27f.tar.bz2 |
[DevTools] Expose DevToolsAgentHost for OOPIF, display it in chrome://inspect.
BUG=451004,464993
Review URL: https://codereview.chromium.org/976313003
Cr-Commit-Position: refs/heads/master@{#319613}
-rw-r--r-- | chrome/browser/devtools/devtools_target_impl.cc | 37 | ||||
-rw-r--r-- | chrome/browser/devtools/devtools_window.cc | 15 | ||||
-rw-r--r-- | chrome/browser/devtools/devtools_window.h | 5 | ||||
-rw-r--r-- | content/browser/devtools/devtools_agent_host_impl.cc | 8 | ||||
-rw-r--r-- | content/browser/devtools/devtools_agent_host_impl.h | 3 | ||||
-rw-r--r-- | content/browser/devtools/render_frame_devtools_agent_host.cc | 60 | ||||
-rw-r--r-- | content/browser/devtools/render_frame_devtools_agent_host.h | 9 | ||||
-rw-r--r-- | content/browser/devtools/site_per_process_devtools_browsertest.cc | 113 | ||||
-rw-r--r-- | content/content_tests.gypi | 1 | ||||
-rw-r--r-- | content/public/browser/devtools_agent_host.h | 3 |
10 files changed, 212 insertions, 42 deletions
diff --git a/chrome/browser/devtools/devtools_target_impl.cc b/chrome/browser/devtools/devtools_target_impl.cc index 23c9411..b03a737 100644 --- a/chrome/browser/devtools/devtools_target_impl.cc +++ b/chrome/browser/devtools/devtools_target_impl.cc @@ -63,18 +63,6 @@ WebContentsTarget::WebContentsTarget(WebContents* web_contents, bool is_tab) tab_id_(-1) { set_type(kTargetTypeOther); - content::RenderFrameHost* rfh = - web_contents->GetRenderViewHost()->GetMainFrame(); - if (rfh->IsCrossProcessSubframe()) { - set_url(rfh->GetLastCommittedURL()); - set_type(kTargetTypeIFrame); - // TODO(pfeldman) Update for out of process iframes. - RenderViewHost* parent_rvh = rfh->GetParent()->GetRenderViewHost(); - set_parent_id(DevToolsAgentHost::GetOrCreateFor( - WebContents::FromRenderViewHost(parent_rvh))->GetId()); - return; - } - content::NavigationController& controller = web_contents->GetController(); content::NavigationEntry* entry = controller.GetActiveEntry(); if (entry != NULL && entry->GetURL().is_valid()) @@ -143,6 +131,28 @@ void WebContentsTarget::Inspect(Profile* profile) const { DevToolsWindow::OpenDevToolsWindow(web_contents); } +// FrameTarget ---------------------------------------------------------------- + +class FrameTarget : public DevToolsTargetImpl { + public: + explicit FrameTarget(scoped_refptr<DevToolsAgentHost> agent_host); + + // DevToolsTargetImpl overrides: + void Inspect(Profile* profile) const override; +}; + +FrameTarget::FrameTarget(scoped_refptr<DevToolsAgentHost> agent_host) + : DevToolsTargetImpl(agent_host) { + set_type(kTargetTypePage); + WebContents* wc = agent_host->GetWebContents(); + DCHECK(DevToolsAgentHost::GetOrCreateFor(wc).get() != agent_host.get()); + set_parent_id(DevToolsAgentHost::GetOrCreateFor(wc)->GetId()); +} + +void FrameTarget::Inspect(Profile* profile) const { + DevToolsWindow::OpenDevToolsWindow(profile, GetAgentHost()); +} + // WorkerTarget ---------------------------------------------------------------- class WorkerTarget : public DevToolsTargetImpl { @@ -281,6 +291,9 @@ void DevToolsTargetImpl::EnumerateAllTargets(Callback callback) { result.push_back(new WebContentsTarget(web_contents, is_tab)); } break; + case DevToolsAgentHost::TYPE_FRAME: + result.push_back(new FrameTarget(agent_host)); + break; case DevToolsAgentHost::TYPE_SHARED_WORKER: result.push_back(new WorkerTarget(agent_host)); break; diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc index a517f18..7806ab0 100644 --- a/chrome/browser/devtools/devtools_window.cc +++ b/chrome/browser/devtools/devtools_window.cc @@ -423,6 +423,21 @@ DevToolsWindow* DevToolsWindow::OpenDevToolsWindow( } // static +DevToolsWindow* DevToolsWindow::OpenDevToolsWindow( + Profile* profile, + const scoped_refptr<content::DevToolsAgentHost>& agent_host) { + DevToolsWindow* window = FindDevToolsWindow(agent_host.get()); + if (!window) { + window = DevToolsWindow::Create( + profile, GURL(), nullptr, false, std::string(), false, std::string()); + DCHECK(window); + window->bindings_->AttachTo(agent_host); + } + window->ScheduleShow(DevToolsToggleAction::Show()); + return window; +} + +// static DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow( Browser* browser, const DevToolsToggleAction& action) { diff --git a/chrome/browser/devtools/devtools_window.h b/chrome/browser/devtools/devtools_window.h index d0a4d3b..ed6b166 100644 --- a/chrome/browser/devtools/devtools_window.h +++ b/chrome/browser/devtools/devtools_window.h @@ -72,6 +72,11 @@ class DevToolsWindow : public DevToolsUIBindings::Delegate, static DevToolsWindow* OpenDevToolsWindow( content::WebContents* inspected_web_contents); + // Open or reveal DevTools window. This window will be undocked. + static DevToolsWindow* OpenDevToolsWindow( + Profile* profile, + const scoped_refptr<content::DevToolsAgentHost>& agent_host); + // Perform specified action for current WebContents inside a |browser|. // This may close currently open DevTools window. static DevToolsWindow* ToggleDevToolsWindow( diff --git a/content/browser/devtools/devtools_agent_host_impl.cc b/content/browser/devtools/devtools_agent_host_impl.cc index 4ac3b99..cc524bc 100644 --- a/content/browser/devtools/devtools_agent_host_impl.cc +++ b/content/browser/devtools/devtools_agent_host_impl.cc @@ -12,6 +12,7 @@ #include "base/lazy_instance.h" #include "content/browser/devtools/devtools_manager.h" #include "content/browser/devtools/forwarding_agent_host.h" +#include "content/browser/devtools/render_frame_devtools_agent_host.h" #include "content/browser/devtools/service_worker_devtools_manager.h" #include "content/browser/devtools/shared_worker_devtools_manager.h" #include "content/public/browser/browser_thread.h" @@ -34,12 +35,7 @@ DevToolsAgentHost::List DevToolsAgentHost::GetOrCreateAll() { List result; SharedWorkerDevToolsManager::GetInstance()->AddAllAgentHosts(&result); ServiceWorkerDevToolsManager::GetInstance()->AddAllAgentHosts(&result); - std::vector<WebContents*> wc_list = - DevToolsAgentHostImpl::GetInspectableWebContents(); - for (std::vector<WebContents*>::iterator it = wc_list.begin(); - it != wc_list.end(); ++it) { - result.push_back(GetOrCreateFor(*it)); - } + RenderFrameDevToolsAgentHost::AddAllAgentHosts(&result); return result; } diff --git a/content/browser/devtools/devtools_agent_host_impl.h b/content/browser/devtools/devtools_agent_host_impl.h index 19b5c30..f48f425 100644 --- a/content/browser/devtools/devtools_agent_host_impl.h +++ b/content/browser/devtools/devtools_agent_host_impl.h @@ -22,9 +22,6 @@ class BrowserContext; // Describes interface for managing devtools agents from the browser process. class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost { public: - // Returns a list of all existing WebContents that can be debugged. - static std::vector<WebContents*> GetInspectableWebContents(); - // Informs the hosted agent that a client host has attached. virtual void Attach() = 0; diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index f30286d..7f6b942 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc @@ -81,6 +81,26 @@ DevToolsAgentHost::GetOrCreateFor(WebContents* web_contents) { } // static +scoped_refptr<DevToolsAgentHost> RenderFrameDevToolsAgentHost::GetOrCreateFor( + RenderFrameHost* host) { + RenderFrameDevToolsAgentHost* result = FindAgentHost(host); + if (!result) + result = new RenderFrameDevToolsAgentHost(host); + return result; +} + +// static +void RenderFrameDevToolsAgentHost::AppendAgentHostForFrameIfApplicable( + DevToolsAgentHost::List* result, + RenderFrameHost* host) { + RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(host); + if (!rfh->IsRenderFrameLive()) + return; + if (rfh->IsCrossProcessSubframe() || !rfh->GetParent()) + result->push_back(RenderFrameDevToolsAgentHost::GetOrCreateFor(rfh)); +} + +// static bool DevToolsAgentHost::HasFor(WebContents* web_contents) { return FindAgentHost(web_contents) != NULL; } @@ -92,25 +112,13 @@ bool DevToolsAgentHost::IsDebuggerAttached(WebContents* web_contents) { } //static -std::vector<WebContents*> DevToolsAgentHostImpl::GetInspectableWebContents() { - std::set<WebContents*> set; - scoped_ptr<RenderWidgetHostIterator> widgets( - RenderWidgetHost::GetRenderWidgetHosts()); - while (RenderWidgetHost* widget = widgets->GetNextHost()) { - // Ignore processes that don't have a connection, such as crashed contents. - if (!widget->GetProcess()->HasConnection()) - continue; - if (!widget->IsRenderView()) - continue; - - RenderViewHost* rvh = RenderViewHost::From(widget); - WebContents* web_contents = WebContents::FromRenderViewHost(rvh); - if (web_contents) - set.insert(web_contents); - } - std::vector<WebContents*> result(set.size()); - std::copy(set.begin(), set.end(), result.begin()); - return result; +void RenderFrameDevToolsAgentHost::AddAllAgentHosts( + DevToolsAgentHost::List* result) { + base::Callback<void(RenderFrameHost*)> callback = base::Bind( + RenderFrameDevToolsAgentHost::AppendAgentHostForFrameIfApplicable, + base::Unretained(result)); + for (const auto& wc : WebContentsImpl::GetAllWebContents()) + wc->ForEachFrame(callback); } // static @@ -409,6 +417,9 @@ void RenderFrameDevToolsAgentHost::Observe(int type, void RenderFrameDevToolsAgentHost::SetRenderFrameHost(RenderFrameHost* rfh) { DCHECK(!render_frame_host_); render_frame_host_ = static_cast<RenderFrameHostImpl*>(rfh); + // TODO(dgozman): here we should DCHECK that frame host is either root or + // cross process subframe, but this requires handling cross-process + // navigation. See http://crbug.com/464993. WebContentsObserver::Observe(WebContents::FromRenderFrameHost(rfh)); RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( @@ -448,17 +459,20 @@ void RenderFrameDevToolsAgentHost::ConnectWebContents(WebContents* wc) { } DevToolsAgentHost::Type RenderFrameDevToolsAgentHost::GetType() { - return TYPE_WEB_CONTENTS; + return IsChildFrame() ? TYPE_FRAME : TYPE_WEB_CONTENTS; } std::string RenderFrameDevToolsAgentHost::GetTitle() { + if (IsChildFrame()) + return GetURL().spec(); if (WebContents* web_contents = GetWebContents()) return base::UTF16ToUTF8(web_contents->GetTitle()); return ""; } GURL RenderFrameDevToolsAgentHost::GetURL() { - if (WebContents* web_contents = GetWebContents()) + WebContents* web_contents = GetWebContents(); + if (web_contents && !IsChildFrame()) return web_contents->GetVisibleURL(); return render_frame_host_ ? render_frame_host_->GetLastCommittedURL() : GURL(); @@ -534,4 +548,8 @@ void RenderFrameDevToolsAgentHost::DispatchOnInspectorFrontend( SendMessageToClient(message); } +bool RenderFrameDevToolsAgentHost::IsChildFrame() { + return render_frame_host_ && render_frame_host_->GetParent(); +} + } // namespace content diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h index 51f12d4..4aed805 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.h +++ b/content/browser/devtools/render_frame_devtools_agent_host.h @@ -48,6 +48,8 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost private WebContentsObserver, public NotificationObserver { public: + static void AddAllAgentHosts(DevToolsAgentHost::List* result); + static void OnCancelPendingNavigation(RenderFrameHost* pending, RenderFrameHost* current); @@ -72,6 +74,11 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost explicit RenderFrameDevToolsAgentHost(RenderFrameHost*); ~RenderFrameDevToolsAgentHost() override; + static scoped_refptr<DevToolsAgentHost> GetOrCreateFor(RenderFrameHost* host); + static void AppendAgentHostForFrameIfApplicable( + DevToolsAgentHost::List* result, + RenderFrameHost* host); + // IPCDevToolsAgentHost overrides. void DispatchProtocolMessage(const std::string& message) override; void SendMessageToAgent(IPC::Message* msg) override; @@ -118,6 +125,8 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost void InnerOnClientAttached(); void InnerClientDetachedFromRenderer(); + bool IsChildFrame(); + RenderFrameHostImpl* render_frame_host_; scoped_ptr<devtools::dom::DOMHandler> dom_handler_; scoped_ptr<devtools::input::InputHandler> input_handler_; diff --git a/content/browser/devtools/site_per_process_devtools_browsertest.cc b/content/browser/devtools/site_per_process_devtools_browsertest.cc new file mode 100644 index 0000000..aaa935f --- /dev/null +++ b/content/browser/devtools/site_per_process_devtools_browsertest.cc @@ -0,0 +1,113 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "content/browser/frame_host/frame_tree.h" +#include "content/browser/site_per_process_browsertest.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/devtools_agent_host.h" +#include "content/public/test/content_browser_test_utils.h" +#include "content/public/test/test_utils.h" +#include "content/shell/browser/shell.h" +#include "content/test/content_browser_test_utils_internal.h" +#include "net/dns/mock_host_resolver.h" + +namespace content { + +class SitePerProcessDevToolsBrowserTest + : public SitePerProcessBrowserTest { + public: + SitePerProcessDevToolsBrowserTest() {} +}; + +class TestClient: public DevToolsAgentHostClient { + public: + TestClient() : closed_(false) {} + ~TestClient() override {} + + bool closed() { return closed_; } + + void DispatchProtocolMessage( + DevToolsAgentHost* agent_host, + const std::string& message) override { + } + + void AgentHostClosed( + DevToolsAgentHost* agent_host, + bool replaced_with_another_client) override { + closed_ = true; + } + + private: + bool closed_; +}; + +// Fails on Android, http://crbug.com/464993. +#if defined(OS_ANDROID) +#define MAYBE_CrossSiteIframeAgentHost DISABLED_CrossSiteIframeAgentHost +#else +#define MAYBE_CrossSiteIframeAgentHost CrossSiteIframeAgentHost +#endif +IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest, + MAYBE_CrossSiteIframeAgentHost) { + DevToolsAgentHost::List list; + host_resolver()->AddRule("*", "127.0.0.1"); + ASSERT_TRUE(test_server()->Start()); + GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); + NavigateToURL(shell(), main_url); + + // It is safe to obtain the root frame tree node here, as it doesn't change. + FrameTreeNode* root = + static_cast<WebContentsImpl*>(shell()->web_contents())-> + GetFrameTree()->root(); + + list = DevToolsAgentHost::GetOrCreateAll(); + EXPECT_EQ(1U, list.size()); + EXPECT_EQ(DevToolsAgentHost::TYPE_WEB_CONTENTS, list[0]->GetType()); + EXPECT_EQ(main_url.spec(), list[0]->GetURL().spec()); + + // Load same-site page into iframe. + FrameTreeNode* child = root->child_at(0); + GURL http_url(test_server()->GetURL("files/title1.html")); + NavigateFrameToURL(child, http_url); + + list = DevToolsAgentHost::GetOrCreateAll(); + EXPECT_EQ(1U, list.size()); + EXPECT_EQ(DevToolsAgentHost::TYPE_WEB_CONTENTS, list[0]->GetType()); + EXPECT_EQ(main_url.spec(), list[0]->GetURL().spec()); + + // Load cross-site page into iframe. + GURL::Replacements replace_host; + GURL cross_site_url(test_server()->GetURL("files/title2.html")); + replace_host.SetHostStr("foo.com"); + cross_site_url = cross_site_url.ReplaceComponents(replace_host); + NavigateFrameToURL(root->child_at(0), cross_site_url); + + list = DevToolsAgentHost::GetOrCreateAll(); + EXPECT_EQ(2U, list.size()); + EXPECT_EQ(DevToolsAgentHost::TYPE_WEB_CONTENTS, list[0]->GetType()); + EXPECT_EQ(main_url.spec(), list[0]->GetURL().spec()); + EXPECT_EQ(DevToolsAgentHost::TYPE_FRAME, list[1]->GetType()); + EXPECT_EQ(cross_site_url.spec(), list[1]->GetURL().spec()); + + // Attaching to child frame. + scoped_refptr<DevToolsAgentHost> child_host = list[1]; + TestClient client; + child_host->AttachClient(&client); + + // Load back same-site page into iframe. + NavigateFrameToURL(root->child_at(0), http_url); + + list = DevToolsAgentHost::GetOrCreateAll(); + EXPECT_EQ(1U, list.size()); + EXPECT_EQ(DevToolsAgentHost::TYPE_WEB_CONTENTS, list[0]->GetType()); + EXPECT_EQ(main_url.spec(), list[0]->GetURL().spec()); + // TODO(dgozman): we should get closed notification here. + // See http://crbug.com/464993. + EXPECT_FALSE(client.closed()); + child_host->DetachClient(); + child_host = nullptr; +} + +} // namespace content diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 82c8e0a..66a6104 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -200,6 +200,7 @@ 'browser/database_browsertest.cc', 'browser/device_sensors/device_inertial_sensor_browsertest.cc', 'browser/devtools/protocol/devtools_protocol_browsertest.cc', + 'browser/devtools/site_per_process_devtools_browsertest.cc', 'browser/dom_storage/dom_storage_browsertest.cc', 'browser/download/download_browsertest.cc', 'browser/download/drag_download_file_browsertest.cc', diff --git a/content/public/browser/devtools_agent_host.h b/content/public/browser/devtools_agent_host.h index 5715fd8..8f0705f 100644 --- a/content/public/browser/devtools_agent_host.h +++ b/content/public/browser/devtools_agent_host.h @@ -29,6 +29,9 @@ class CONTENT_EXPORT DevToolsAgentHost // Agent host associated with WebContents. TYPE_WEB_CONTENTS, + // Agent host associated with RenderFrameHost. + TYPE_FRAME, + // Agent host associated with shared worker. TYPE_SHARED_WORKER, |