diff options
author | kaznacheev@chromium.org <kaznacheev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-12 08:47:54 +0000 |
---|---|---|
committer | kaznacheev@chromium.org <kaznacheev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-12 08:47:54 +0000 |
commit | ead05635816265f14f92243baa56f40d4a31c01e (patch) | |
tree | f7ec7ca43de2cd36a26b4547816acf6a7580a274 | |
parent | 3e5a076165f61312818e92ab712ade50e210c696 (diff) | |
download | chromium_src-ead05635816265f14f92243baa56f40d4a31c01e.zip chromium_src-ead05635816265f14f92243baa56f40d4a31c01e.tar.gz chromium_src-ead05635816265f14f92243baa56f40d4a31c01e.tar.bz2 |
This is required to simplify the implementation of chrome.debugger.getTargets.
BUG=179342
Review URL: https://codereview.chromium.org/12319114
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@187540 0039d316-1c4b-4281-b951-d872f2087c98
12 files changed, 282 insertions, 151 deletions
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc index 67a61c2..40d03eb 100644 --- a/chrome/browser/devtools/devtools_sanity_browsertest.cc +++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc @@ -11,7 +11,9 @@ #include "base/stringprintf.h" #include "base/test/test_timeouts.h" #include "base/utf_string_conversions.h" +#include "chrome/browser/devtools/browser_list_tabcontents_provider.h" #include "chrome/browser/devtools/devtools_window.h" +#include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_system.h" #include "chrome/browser/extensions/unpacked_installer.h" @@ -29,6 +31,7 @@ #include "content/public/browser/content_browser_client.h" #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_client_host.h" +#include "content/public/browser/devtools_http_handler.h" #include "content/public/browser/devtools_manager.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_service.h" @@ -37,6 +40,7 @@ #include "content/public/browser/worker_service.h" #include "content/public/browser/worker_service_observer.h" #include "content/public/test/browser_test_utils.h" +#include "net/base/tcp_listen_socket.h" #include "net/test/test_server.h" using content::BrowserThread; @@ -610,4 +614,74 @@ IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestAddMessageToConsole) { CloseDevToolsWindow(); } +class RemoteDebuggingTest : public ExtensionBrowserTest { + + class ResultCatcher : public content::NotificationObserver { + public: + ResultCatcher() + : notification_(chrome::NOTIFICATION_CHROME_END) { + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_TEST_PASSED, + content::NotificationService::AllSources()); + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_TEST_FAILED, + content::NotificationService::AllSources()); + } + + virtual ~ResultCatcher() { + } + + // Pumps the UI loop until a notification is received that an API test + // succeeded or failed. Returns true if the test succeeded, false otherwise. + bool GetNextResult() { + if (!received()) + content::RunMessageLoop(); + + if (!received()) + NOTREACHED(); + + return notification_ == chrome::NOTIFICATION_EXTENSION_TEST_PASSED; + } + + private: + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE { + if (received()) + return; + notification_ = static_cast<chrome::NotificationType>(type); + MessageLoopForUI::current()->Quit(); + } + + content::NotificationRegistrar registrar_; + + chrome::NotificationType notification_; + + bool received() { return notification_ != chrome::NOTIFICATION_CHROME_END; } + }; + + protected: + + bool RunExtensionTest(const std::string& directory) { + content::DevToolsHttpHandler* devtools_http_handler_ = + content::DevToolsHttpHandler::Start( + new net::TCPListenSocketFactory("127.0.0.1", 9222), + "", + new BrowserListTabContentsProvider( + profile(), chrome::HOST_DESKTOP_TYPE_NATIVE)); + + base::FilePath test_data_path; + PathService::Get(chrome::DIR_TEST_DATA, &test_data_path); + LoadExtension( + test_data_path.AppendASCII("devtools").AppendASCII(directory)); + + ResultCatcher catcher; + bool result = catcher.GetNextResult(); + devtools_http_handler_->Stop(); + return result; + } +}; + +IN_PROC_BROWSER_TEST_F(RemoteDebuggingTest, TargetList) { + ASSERT_TRUE(RunExtensionTest("target_list")); +} + } // namespace diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index ebe016b..a041040 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc @@ -728,9 +728,9 @@ void ExtensionService::ReloadExtensionWithEvents( manager->GetBackgroundHostForExtension(extension_id); if (host && DevToolsAgentHost::HasFor(host->render_view_host())) { // Look for an open inspector for the background page. - int devtools_cookie = DevToolsAgentHost::DisconnectRenderViewHost( + std::string devtools_cookie = DevToolsAgentHost::DisconnectRenderViewHost( host->render_view_host()); - if (devtools_cookie >= 0) + if (devtools_cookie != std::string()) orphaned_dev_tools_[extension_id] = devtools_cookie; } diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h index 0ddd9c8..f12d92b 100644 --- a/chrome/browser/extensions/extension_service.h +++ b/chrome/browser/extensions/extension_service.h @@ -912,7 +912,7 @@ class ExtensionService // Map of inspector cookies that are detached, waiting for an extension to be // reloaded. - typedef std::map<std::string, int> OrphanedDevTools; + typedef std::map<std::string, std::string> OrphanedDevTools; OrphanedDevTools orphaned_dev_tools_; // Maps extension ids to a bitmask that indicates which events should be diff --git a/chrome/test/data/devtools/target_list/background.js b/chrome/test/data/devtools/target_list/background.js new file mode 100644 index 0000000..4fb3d92 --- /dev/null +++ b/chrome/test/data/devtools/target_list/background.js @@ -0,0 +1,62 @@ +// Copyright (c) 2013 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. + +function requestUrl(url, callback) { + var req = new XMLHttpRequest(); + req.open('GET', url, true); + req.onload = function() { + if (req.status == 200) + callback(req.responseText); + else + req.onerror(); + }; + req.onerror = function() { + chrome.test.fail('XHR failed: ' + req.status); + }; + req.send(null); +} + +var REMOTE_DEBUGGER_HOST = 'localhost:9222'; + +function checkTarget(targets, url, type, opt_title, opt_faviconUrl) { + var target = + targets.filter(function(t) { return t.url == url }) [0]; + if (!target) + chrome.test.fail('Cannot find a target with url ' + url); + + var wsAddress = REMOTE_DEBUGGER_HOST + '/devtools/page/' + target.id; + + chrome.test.assertEq( + '/devtools/devtools.html?ws=' + wsAddress, + target.devtoolsFrontendUrl); + chrome.test.assertEq(opt_faviconUrl || '', target.faviconUrl); + chrome.test.assertEq('/thumb/' + target.id, target.thumbnailUrl); + chrome.test.assertEq(opt_title || target.url, target.title); + chrome.test.assertEq(type, target.type); + chrome.test.assertEq('ws://' + wsAddress, target.webSocketDebuggerUrl); +} + +chrome.test.runTests([ + function discoverTargets() { + var testPageUrl = chrome.extension.getURL('test_page.html'); + + function onUpdated() { + chrome.tabs.onUpdated.removeListener(onUpdated); + requestUrl('http://' + REMOTE_DEBUGGER_HOST + '/json', function(text) { + var targets = JSON.parse(text); + + checkTarget(targets, 'about:blank', 'page'); + checkTarget(targets, testPageUrl, 'page', 'Test page', + chrome.extension.getURL('favicon.png')); + checkTarget(targets, + chrome.extension.getURL('_generated_background_page.html'), + 'other'); + + chrome.test.succeed(); + }); + } + chrome.tabs.onUpdated.addListener(onUpdated); + chrome.tabs.create({url: testPageUrl}); + } +]); diff --git a/chrome/test/data/devtools/target_list/manifest.json b/chrome/test/data/devtools/target_list/manifest.json new file mode 100644 index 0000000..19dfdfc --- /dev/null +++ b/chrome/test/data/devtools/target_list/manifest.json @@ -0,0 +1,11 @@ +{ + "name": "Remote Debugger Test", + "version": "1.0", + "manifest_version": 2, + "background": { + "scripts": ["background.js"] + }, + "permissions": [ + "http://*/" + ] +} diff --git a/chrome/test/data/devtools/target_list/test_page.html b/chrome/test/data/devtools/target_list/test_page.html new file mode 100644 index 0000000..eb7ed70 --- /dev/null +++ b/chrome/test/data/devtools/target_list/test_page.html @@ -0,0 +1,6 @@ +<html> +<head> + <title>Test page</title> + <link rel="icon" type="image/png" href="/favicon.png" /> +</head> +</html> diff --git a/content/browser/devtools/devtools_agent_host_impl.cc b/content/browser/devtools/devtools_agent_host_impl.cc index 0474103..cb2b31e 100644 --- a/content/browser/devtools/devtools_agent_host_impl.cc +++ b/content/browser/devtools/devtools_agent_host_impl.cc @@ -5,6 +5,7 @@ #include "content/browser/devtools/devtools_agent_host_impl.h" #include "base/basictypes.h" +#include "base/stringprintf.h" #include "content/common/devtools_messages.h" namespace content { @@ -15,7 +16,7 @@ static int g_next_agent_host_id = 0; DevToolsAgentHostImpl::DevToolsAgentHostImpl() : close_listener_(NULL), - id_(++g_next_agent_host_id) { + id_(base::StringPrintf("%d", ++g_next_agent_host_id)) { } void DevToolsAgentHostImpl::Attach() { @@ -54,6 +55,10 @@ void DevToolsAgentHostImpl::AddMessageToConsole(ConsoleMessageLevel level, message)); } +std::string DevToolsAgentHostImpl::GetId() { + return id_; +} + RenderViewHost* DevToolsAgentHostImpl::GetRenderViewHost() { return NULL; } diff --git a/content/browser/devtools/devtools_agent_host_impl.h b/content/browser/devtools/devtools_agent_host_impl.h index c3a5215..5e9cdfb 100644 --- a/content/browser/devtools/devtools_agent_host_impl.h +++ b/content/browser/devtools/devtools_agent_host_impl.h @@ -41,9 +41,9 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost { close_listener_ = listener; } - int id() { return id_; } - // DevToolsAgentHost implementation. + virtual std::string GetId() OVERRIDE; + virtual RenderViewHost* GetRenderViewHost() OVERRIDE; protected: @@ -59,7 +59,7 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost { CloseListener* close_listener_; private: - int id_; + const std::string id_; }; } // namespace content diff --git a/content/browser/devtools/devtools_http_handler_impl.cc b/content/browser/devtools/devtools_http_handler_impl.cc index 461c51f..3106df0 100644 --- a/content/browser/devtools/devtools_http_handler_impl.cc +++ b/content/browser/devtools/devtools_http_handler_impl.cc @@ -15,14 +15,11 @@ #include "base/logging.h" #include "base/message_loop_proxy.h" #include "base/string_number_conversions.h" -#include "base/stringprintf.h" #include "base/threading/thread.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "content/browser/devtools/devtools_agent_host_impl.h" #include "content/browser/devtools/devtools_browser_target.h" #include "content/browser/devtools/devtools_tracing_handler.h" -#include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/devtools_messages.h" #include "content/public/browser/browser_thread.h" @@ -34,9 +31,7 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" -#include "content/public/browser/render_widget_host.h" #include "content/public/common/content_client.h" #include "content/public/common/url_constants.h" #include "googleurl/src/gurl.h" @@ -59,6 +54,8 @@ namespace { static const char* kDevToolsHandlerThreadName = "Chrome_DevToolsHandlerThread"; +static const char* kThumbUrlPrefix = "/thumb/"; + class DevToolsDefaultBindingHandler : public DevToolsHttpHandler::DevToolsAgentHostBinding { public: @@ -77,9 +74,7 @@ class DevToolsDefaultBindingHandler virtual std::string GetIdentifier(DevToolsAgentHost* agent_host) OVERRIDE { GarbageCollect(); - DevToolsAgentHostImpl* agent_host_impl = - static_cast<DevToolsAgentHostImpl*>(agent_host); - std::string id = base::StringPrintf("%d", agent_host_impl->id()); + std::string id = agent_host->GetId(); agents_map_[id] = agent_host; return id; } @@ -157,6 +152,20 @@ class DevToolsClientHostImpl : public DevToolsClientHost { std::string detach_reason_; }; +static base::TimeTicks GetLastSelectedTime(RenderViewHost* rvh) { + WebContents* web_contents = rvh->GetDelegate()->GetAsWebContents(); + if (!web_contents) + return base::TimeTicks(); + + return web_contents->GetLastSelectedTime(); +} + +typedef std::pair<RenderViewHost*, base::TimeTicks> PageInfo; + +static bool TimeComparator(const PageInfo& info1, const PageInfo& info2) { + return info1.second > info2.second; +} + } // namespace // static @@ -308,15 +317,23 @@ void DevToolsHttpHandlerImpl::OnHttpRequest( return; } - if (info.path.find("/thumb/") == 0) { + if (info.path.find(kThumbUrlPrefix) == 0) { // Thumbnail request. + const std::string target_id = info.path.substr(strlen(kThumbUrlPrefix)); + DevToolsAgentHost* agent_host = binding_->ForIdentifier(target_id); + GURL page_url; + if (agent_host) { + RenderViewHost* rvh = agent_host->GetRenderViewHost(); + if (rvh) + page_url = rvh->GetDelegate()->GetURL(); + } BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&DevToolsHttpHandlerImpl::OnThumbnailRequestUI, this, connection_id, - info)); + page_url)); return; } @@ -395,60 +412,6 @@ void DevToolsHttpHandlerImpl::OnClose(int connection_id) { connection_id)); } -struct DevToolsHttpHandlerImpl::PageInfo { - PageInfo() - : attached(false) { - } - - std::string id; - std::string url; - std::string type; - bool attached; - std::string title; - std::string thumbnail_url; - std::string favicon_url; - std::string description; - base::TimeTicks last_selected_time; -}; - -// static -bool DevToolsHttpHandlerImpl::SortPageListByTime(const PageInfo& info1, - const PageInfo& info2) { - return info1.last_selected_time > info2.last_selected_time; -} - -DevToolsHttpHandlerImpl::PageList DevToolsHttpHandlerImpl::GeneratePageList() { - PageList page_list; - for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); - !it.IsAtEnd(); it.Advance()) { - RenderProcessHost* render_process_host = it.GetCurrentValue(); - DCHECK(render_process_host); - - // Ignore processes that don't have a connection, such as crashed contents. - if (!render_process_host->HasConnection()) - continue; - - RenderProcessHost::RenderWidgetHostsIterator rwit( - render_process_host->GetRenderWidgetHostsIterator()); - for (; !rwit.IsAtEnd(); rwit.Advance()) { - const RenderWidgetHost* widget = rwit.GetCurrentValue(); - DCHECK(widget); - if (!widget || !widget->IsRenderView()) - continue; - - RenderViewHost* host = - RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); - // Don't report swapped out views. - if (static_cast<RenderViewHostImpl*>(host)->is_swapped_out()) - continue; - - page_list.push_back(CreatePageInfo(host, delegate_->GetTargetType(host))); - } - } - std::sort(page_list.begin(), page_list.end(), SortPageListByTime); - return page_list; -} - std::string DevToolsHttpHandlerImpl::GetFrontendURLInternal( const std::string rvh_id, const std::string& host) { @@ -532,11 +495,21 @@ void DevToolsHttpHandlerImpl::OnJsonRequestUI( } if (command == "list") { - PageList page_list = GeneratePageList(); + typedef std::vector<PageInfo> PageList; + PageList page_list; + + std::vector<RenderViewHost*> rvh_list = + DevToolsAgentHost::GetValidRenderViewHosts(); + for (std::vector<RenderViewHost*>::iterator it = rvh_list.begin(); + it != rvh_list.end(); ++it) + page_list.push_back(PageInfo(*it, GetLastSelectedTime(*it))); + + std::sort(page_list.begin(), page_list.end(), TimeComparator); + base::ListValue json_pages_list; std::string host = info.headers["Host"]; for (PageList::iterator i = page_list.begin(); i != page_list.end(); ++i) - json_pages_list.Append(SerializePageInfo(*i, host)); + json_pages_list.Append(SerializePageInfo(i->first, host)); SendJson(connection_id, net::HTTP_OK, &json_pages_list, "", jsonp); return; } @@ -551,11 +524,8 @@ void DevToolsHttpHandlerImpl::OnJsonRequestUI( jsonp); return; } - PageInfo page_info = - CreatePageInfo(rvh, DevToolsHttpHandlerDelegate::kTargetTypeTab); std::string host = info.headers["Host"]; - scoped_ptr<base::DictionaryValue> dictionary( - SerializePageInfo(page_info, host)); + scoped_ptr<base::DictionaryValue> dictionary(SerializePageInfo(rvh, host)); SendJson(connection_id, net::HTTP_OK, dictionary.get(), "", jsonp); return; } @@ -593,17 +563,8 @@ void DevToolsHttpHandlerImpl::OnJsonRequestUI( } void DevToolsHttpHandlerImpl::OnThumbnailRequestUI( - int connection_id, - const net::HttpServerRequestInfo& info) { - std::string prefix = "/thumb/"; - size_t pos = info.path.find(prefix); - if (pos != 0) { - Send404(connection_id); - return; - } - - std::string page_url = info.path.substr(prefix.length()); - std::string data = delegate_->GetPageThumbnailData(GURL(page_url)); + int connection_id, const GURL& page_url) { + std::string data = delegate_->GetPageThumbnailData(page_url); if (!data.empty()) Send200(connection_id, data, "image/png"); else @@ -843,66 +804,49 @@ void DevToolsHttpHandlerImpl::AcceptWebSocket( connection_id, request)); } -DevToolsHttpHandlerImpl::PageInfo -DevToolsHttpHandlerImpl::CreatePageInfo(RenderViewHost* rvh, - DevToolsHttpHandlerDelegate::TargetType type) { - RenderViewHostDelegate* host_delegate = rvh->GetDelegate(); +base::DictionaryValue* DevToolsHttpHandlerImpl::SerializePageInfo( + RenderViewHost* rvh, + const std::string& host) { + base::DictionaryValue* dictionary = new base::DictionaryValue; + scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetFor(rvh)); - DevToolsClientHost* client_host = DevToolsManager::GetInstance()-> - GetDevToolsClientHostFor(agent); - PageInfo page_info; - page_info.id = binding_->GetIdentifier(agent); - page_info.attached = client_host != NULL; - page_info.url = host_delegate->GetURL().spec(); - - switch (type) { + + std::string id = binding_->GetIdentifier(agent); + dictionary->SetString("id", id); + + switch (delegate_->GetTargetType(rvh)) { case DevToolsHttpHandlerDelegate::kTargetTypeTab: - page_info.type = "page"; + dictionary->SetString("type", "page"); break; default: - page_info.type = "other"; + dictionary->SetString("type", "other"); } - WebContents* web_contents = host_delegate->GetAsWebContents(); + WebContents* web_contents = rvh->GetDelegate()->GetAsWebContents(); if (web_contents) { - page_info.title = UTF16ToUTF8( - net::EscapeForHTML(web_contents->GetTitle())); - page_info.last_selected_time = web_contents->GetLastSelectedTime(); + dictionary->SetString("title", UTF16ToUTF8( + net::EscapeForHTML(web_contents->GetTitle()))); + dictionary->SetString("url", web_contents->GetURL().spec()); + dictionary->SetString("thumbnailUrl", std::string(kThumbUrlPrefix) + id); NavigationController& controller = web_contents->GetController(); NavigationEntry* entry = controller.GetActiveEntry(); if (entry != NULL && entry->GetURL().is_valid()) { - page_info.thumbnail_url = "/thumb/" + entry->GetURL().spec(); - page_info.favicon_url = entry->GetFavicon().url.spec(); + dictionary->SetString("faviconUrl", entry->GetFavicon().url.spec()); } } - page_info.description = delegate_->GetViewDescription(rvh); - - return page_info; -} - -base::DictionaryValue* DevToolsHttpHandlerImpl::SerializePageInfo( - const PageInfo& page_info, - const std::string& host) { - base::DictionaryValue* dictionary = new base::DictionaryValue; - dictionary->SetString("title", page_info.title); - dictionary->SetString("url", page_info.url); - dictionary->SetString("type", page_info.type); - dictionary->SetString("id", page_info.id); - dictionary->SetString("thumbnailUrl", page_info.thumbnail_url); - dictionary->SetString("faviconUrl", page_info.favicon_url); - if (!page_info.attached) { + if (!DevToolsManager::GetInstance()->GetDevToolsClientHostFor(agent)) { dictionary->SetString("webSocketDebuggerUrl", base::StringPrintf("ws://%s/devtools/page/%s", host.c_str(), - page_info.id.c_str())); + id.c_str())); std::string devtools_frontend_url = GetFrontendURLInternal( - page_info.id.c_str(), + id.c_str(), host); dictionary->SetString("devtoolsFrontendUrl", devtools_frontend_url); } - dictionary->SetString("description", page_info.description); + dictionary->SetString("description", delegate_->GetViewDescription(rvh)); return dictionary; } diff --git a/content/browser/devtools/devtools_http_handler_impl.h b/content/browser/devtools/devtools_http_handler_impl.h index dd027ee..77d7283 100644 --- a/content/browser/devtools/devtools_http_handler_impl.h +++ b/content/browser/devtools/devtools_http_handler_impl.h @@ -41,13 +41,9 @@ class DevToolsHttpHandlerImpl public base::RefCountedThreadSafe<DevToolsHttpHandlerImpl>, public net::HttpServer::Delegate { private: - struct PageInfo; - typedef std::vector<PageInfo> PageList; friend class base::RefCountedThreadSafe<DevToolsHttpHandlerImpl>; friend class DevToolsHttpHandler; - static bool SortPageListByTime(const PageInfo& info1, const PageInfo& info2); - // Takes ownership over |socket_factory|. DevToolsHttpHandlerImpl(const net::StreamListenSocketFactory* socket_factory, const std::string& frontend_url, @@ -78,8 +74,7 @@ class DevToolsHttpHandlerImpl void OnJsonRequestUI(int connection_id, const net::HttpServerRequestInfo& info); - void OnThumbnailRequestUI(int connection_id, - const net::HttpServerRequestInfo& info); + void OnThumbnailRequestUI(int connection_id, const GURL& page_url); void OnDiscoveryPageRequestUI(int connection_id); void OnWebSocketRequestUI(int connection_id, @@ -110,16 +105,11 @@ class DevToolsHttpHandlerImpl void AcceptWebSocket(int connection_id, const net::HttpServerRequestInfo& request); - PageList GeneratePageList(); - // Returns the front end url without the host at the beginning. std::string GetFrontendURLInternal(const std::string rvh_id, const std::string& host); - PageInfo CreatePageInfo(RenderViewHost* rvh, - DevToolsHttpHandlerDelegate::TargetType type); - - base::DictionaryValue* SerializePageInfo(const PageInfo& page_info, + base::DictionaryValue* SerializePageInfo(RenderViewHost* rvh, const std::string& host); // The thread used by the devtools handler to run server socket. diff --git a/content/browser/devtools/render_view_devtools_agent_host.cc b/content/browser/devtools/render_view_devtools_agent_host.cc index 26b14bf..6bbb103 100644 --- a/content/browser/devtools/render_view_devtools_agent_host.cc +++ b/content/browser/devtools/render_view_devtools_agent_host.cc @@ -104,32 +104,64 @@ bool DevToolsAgentHost::IsDebuggerAttached(WebContents* web_contents) { } // static -int DevToolsAgentHost::DisconnectRenderViewHost(RenderViewHost* rvh) { +std::string DevToolsAgentHost::DisconnectRenderViewHost(RenderViewHost* rvh) { RenderViewDevToolsAgentHost* agent_host = FindAgentHost(rvh); if (!agent_host) - return -1; + return std::string(); agent_host->DisconnectRenderViewHost(); - return agent_host->id(); + return agent_host->GetId(); } // static -void DevToolsAgentHost::ConnectRenderViewHost(int cookie, +void DevToolsAgentHost::ConnectRenderViewHost(const std::string& cookie, RenderViewHost* rvh) { for (Instances::iterator it = g_instances.Get().begin(); it != g_instances.Get().end(); ++it) { - if (cookie == (*it)->id()) { + if (cookie == (*it)->GetId()) { (*it)->ConnectRenderViewHost(rvh, true); break; } } } +//static +std::vector<RenderViewHost*> DevToolsAgentHost::GetValidRenderViewHosts() { + std::vector<RenderViewHost*> result; + for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); + !it.IsAtEnd(); it.Advance()) { + RenderProcessHost* render_process_host = it.GetCurrentValue(); + DCHECK(render_process_host); + + // Ignore processes that don't have a connection, such as crashed contents. + if (!render_process_host->HasConnection()) + continue; + + RenderProcessHost::RenderWidgetHostsIterator rwit( + render_process_host->GetRenderWidgetHostsIterator()); + for (; !rwit.IsAtEnd(); rwit.Advance()) { + const RenderWidgetHost* widget = rwit.GetCurrentValue(); + DCHECK(widget); + if (!widget || !widget->IsRenderView()) + continue; + + RenderViewHost* rvh = + RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); + // Don't report swapped out views. + if (static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out()) + continue; + + result.push_back(rvh); + } + } + return result; +} + // static void RenderViewDevToolsAgentHost::OnCancelPendingNavigation( RenderViewHost* pending, RenderViewHost* current) { - int cookie = DevToolsAgentHost::DisconnectRenderViewHost(pending); - if (cookie != -1) + std::string cookie = DevToolsAgentHost::DisconnectRenderViewHost(pending); + if (cookie != std::string()) DevToolsAgentHost::ConnectRenderViewHost(cookie, current); } diff --git a/content/public/browser/devtools_agent_host.h b/content/public/browser/devtools_agent_host.h index 533c31d..8395b2d 100644 --- a/content/public/browser/devtools_agent_host.h +++ b/content/public/browser/devtools_agent_host.h @@ -6,6 +6,7 @@ #define CONTENT_PUBLIC_BROWSER_DEVTOOLS_AGENT_HOST_H_ #include <string> +#include <vector> #include "base/basictypes.h" #include "base/memory/ref_counted.h" @@ -35,16 +36,22 @@ class CONTENT_EXPORT DevToolsAgentHost static bool IsDebuggerAttached(WebContents* web_contents); - // Detaches given |rvh| from the agent host temporarily and returns a cookie - // that allows to reattach another rvh to that agen thost later. Returns -1 if - // there is no agent host associated with the |rvh|. - static int DisconnectRenderViewHost(RenderViewHost* rvh); + // Detaches given |rvh| from the agent host temporarily and returns the agent + // host id that allows to reattach another rvh to that agent host later. + // Returns empty string if there is no agent host associated with the |rvh|. + static std::string DisconnectRenderViewHost(RenderViewHost* rvh); // Reattaches agent host detached with DisconnectRenderViewHost method above // to |rvh|. - static void ConnectRenderViewHost(int agent_host_cookie, + static void ConnectRenderViewHost(const std::string& agent_host_cookie, RenderViewHost* rvh); + // Returns a list of all existing RenderViewHost's that can be debugged. + static std::vector<RenderViewHost*> GetValidRenderViewHosts(); + + // Returns the unique id of the agent. + virtual std::string GetId() = 0; + // Returns render view host instance for this host if any. virtual RenderViewHost* GetRenderViewHost() = 0; |