summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgozman <dgozman@chromium.org>2015-03-09 06:07:57 -0700
committerCommit bot <commit-bot@chromium.org>2015-03-09 13:08:21 +0000
commitea764811d0f4a41ef8bb9768737bc6f7dde6f27f (patch)
treed900f50ba3263671ecf1ba68efca3d9b1b42f01a
parent7999b8831356451de5559653df030f1a3acc38b7 (diff)
downloadchromium_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.cc37
-rw-r--r--chrome/browser/devtools/devtools_window.cc15
-rw-r--r--chrome/browser/devtools/devtools_window.h5
-rw-r--r--content/browser/devtools/devtools_agent_host_impl.cc8
-rw-r--r--content/browser/devtools/devtools_agent_host_impl.h3
-rw-r--r--content/browser/devtools/render_frame_devtools_agent_host.cc60
-rw-r--r--content/browser/devtools/render_frame_devtools_agent_host.h9
-rw-r--r--content/browser/devtools/site_per_process_devtools_browsertest.cc113
-rw-r--r--content/content_tests.gypi1
-rw-r--r--content/public/browser/devtools_agent_host.h3
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,