From 3a29ade7a13ef2e763f330cdb0df4b5bd459c600 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Wed, 22 Aug 2018 17:05:13 +0000 Subject: [PATCH] DevTools: move browser context management to devtools_manager_delegate This patch: - moves browser context management to devtools_manager_delegate - implements browser context related protocol methods in content/ R=dgozman Bug: 631464 Change-Id: Ia43343d5c2208556214b41225cb05f744f2d9ccd Reviewed-on: https://chromium-review.googlesource.com/1183594 Commit-Queue: Andrey Lushnikov Reviewed-by: Dmitry Gozman Cr-Commit-Position: refs/heads/master@{#585102} --- chrome/browser/devtools/BUILD.gn | 2 + .../chrome_devtools_manager_delegate.cc | 17 ++ .../chrome_devtools_manager_delegate.h | 6 + .../devtools_browser_context_manager.cc | 122 +++++++++++++ .../devtools_browser_context_manager.h | 43 +++++ .../devtools/inspector_protocol_config.json | 3 +- .../devtools/protocol/target_handler.cc | 160 +----------------- .../devtools/protocol/target_handler.h | 7 - .../devtools/protocol/target_handler.cc | 75 ++++++-- .../devtools/protocol/target_handler.h | 4 +- content/browser/devtools/protocol_config.json | 3 +- .../browser/devtools_manager_delegate.cc | 14 ++ .../browser/devtools_manager_delegate.h | 13 ++ .../headless_devtools_manager_delegate.cc | 36 ++++ .../headless_devtools_manager_delegate.h | 5 + .../lib/browser/protocol/target_handler.cc | 40 ----- .../lib/browser/protocol/target_handler.h | 5 - headless/protocol_config.json | 2 +- 18 files changed, 329 insertions(+), 228 deletions(-) create mode 100644 chrome/browser/devtools/devtools_browser_context_manager.cc create mode 100644 chrome/browser/devtools/devtools_browser_context_manager.h diff --git a/chrome/browser/devtools/BUILD.gn b/chrome/browser/devtools/BUILD.gn index d43ebd43b747da..8e4c3ab3e21896 100644 --- a/chrome/browser/devtools/BUILD.gn +++ b/chrome/browser/devtools/BUILD.gn @@ -145,6 +145,8 @@ static_library("devtools") { "device/usb/usb_device_provider.h", "devtools_auto_opener.cc", "devtools_auto_opener.h", + "devtools_browser_context_manager.cc", + "devtools_browser_context_manager.h", "devtools_contents_resizing_strategy.cc", "devtools_contents_resizing_strategy.h", "devtools_embedder_message_dispatcher.cc", diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc index 5414c897a9276c..6884dddd0a356d 100644 --- a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc +++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc @@ -11,6 +11,7 @@ #include "chrome/browser/devtools/chrome_devtools_session.h" #include "chrome/browser/devtools/device/android_device_manager.h" #include "chrome/browser/devtools/device/tcp_device_provider.h" +#include "chrome/browser/devtools/devtools_browser_context_manager.h" #include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/devtools/protocol/target_handler.h" #include "chrome/browser/extensions/extension_tab_util.h" @@ -221,6 +222,22 @@ std::string ChromeDevToolsManagerDelegate::GetDiscoveryPageHTML() { .as_string(); } +std::vector +ChromeDevToolsManagerDelegate::GetBrowserContexts() { + return DevToolsBrowserContextManager::GetInstance().GetBrowserContexts(); +} + +content::BrowserContext* ChromeDevToolsManagerDelegate::CreateBrowserContext() { + return DevToolsBrowserContextManager::GetInstance().CreateBrowserContext(); +} + +void ChromeDevToolsManagerDelegate::DisposeBrowserContext( + content::BrowserContext* context, + DisposeCallback callback) { + DevToolsBrowserContextManager::GetInstance().DisposeBrowserContext( + context, std::move(callback)); +} + bool ChromeDevToolsManagerDelegate::HasBundledFrontendResources() { return true; } diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.h b/chrome/browser/devtools/chrome_devtools_manager_delegate.h index 99449309edbbce..087d00c85844eb 100644 --- a/chrome/browser/devtools/chrome_devtools_manager_delegate.h +++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.h @@ -58,6 +58,12 @@ class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate { NotHandledCallback callback) override; std::string GetTargetType(content::WebContents* web_contents) override; std::string GetTargetTitle(content::WebContents* web_contents) override; + + std::vector GetBrowserContexts() override; + content::BrowserContext* CreateBrowserContext() override; + void DisposeBrowserContext(content::BrowserContext*, + DisposeCallback callback) override; + bool AllowInspectingWebContents(content::WebContents* web_contents) override; void ClientAttached(content::DevToolsAgentHost* agent_host, content::DevToolsAgentHostClient* client) override; diff --git a/chrome/browser/devtools/devtools_browser_context_manager.cc b/chrome/browser/devtools/devtools_browser_context_manager.cc new file mode 100644 index 00000000000000..b3d629cc0064de --- /dev/null +++ b/chrome/browser/devtools/devtools_browser_context_manager.cc @@ -0,0 +1,122 @@ +// Copyright 2018 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/devtools/devtools_browser_context_manager.h" + +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" + +DevToolsBrowserContextManager::DevToolsBrowserContextManager() + : weak_factory_(this) {} + +DevToolsBrowserContextManager::~DevToolsBrowserContextManager() = default; + +// static +DevToolsBrowserContextManager& DevToolsBrowserContextManager::GetInstance() { + static base::NoDestructor instance; + return *instance; +} + +Profile* DevToolsBrowserContextManager::GetProfileById( + const std::string& context_id) { + auto it = registrations_.find(context_id); + if (it == registrations_.end()) + return nullptr; + return it->second->profile(); +} + +content::BrowserContext* DevToolsBrowserContextManager::CreateBrowserContext() { + Profile* original_profile = + ProfileManager::GetActiveUserProfile()->GetOriginalProfile(); + + auto registration = + IndependentOTRProfileManager::GetInstance()->CreateFromOriginalProfile( + original_profile, + base::BindOnce( + &DevToolsBrowserContextManager::OnOriginalProfileDestroyed, + weak_factory_.GetWeakPtr())); + content::BrowserContext* context = registration->profile(); + const std::string& context_id = context->UniqueId(); + registrations_[context_id] = std::move(registration); + return context; +} + +std::vector +DevToolsBrowserContextManager::GetBrowserContexts() { + std::vector result; + for (const auto& registration_pair : registrations_) + result.push_back(registration_pair.second->profile()); + return result; +} + +void DevToolsBrowserContextManager::DisposeBrowserContext( + content::BrowserContext* context, + content::DevToolsManagerDelegate::DisposeCallback callback) { + std::string context_id = context->UniqueId(); + if (pending_context_disposals_.find(context_id) != + pending_context_disposals_.end()) { + std::move(callback).Run(false, "Disposal of browser context " + context_id + + " is already pending"); + return; + } + auto it = registrations_.find(context_id); + if (it == registrations_.end()) { + std::move(callback).Run( + false, "Failed to find browser context with id " + context_id); + return; + } + + Profile* profile = it->second->profile(); + bool has_opened_browser = false; + for (auto* opened_browser : *BrowserList::GetInstance()) { + if (opened_browser->profile() == profile) { + has_opened_browser = true; + break; + } + } + + // If no browsers are opened - dispose right away. + if (!has_opened_browser) { + registrations_.erase(it); + std::move(callback).Run(true, ""); + return; + } + + if (pending_context_disposals_.empty()) + BrowserList::AddObserver(this); + + pending_context_disposals_[context_id] = std::move(callback); + BrowserList::CloseAllBrowsersWithIncognitoProfile( + profile, base::DoNothing(), base::DoNothing(), + true /* skip_beforeunload */); +} + +void DevToolsBrowserContextManager::OnOriginalProfileDestroyed( + Profile* profile) { + base::EraseIf(registrations_, [&profile](const auto& it) { + return it.second->profile()->GetOriginalProfile() == profile; + }); +} + +void DevToolsBrowserContextManager::OnBrowserRemoved(Browser* browser) { + std::string context_id = browser->profile()->UniqueId(); + auto pending_disposal = pending_context_disposals_.find(context_id); + if (pending_disposal == pending_context_disposals_.end()) + return; + for (auto* opened_browser : *BrowserList::GetInstance()) { + if (opened_browser->profile() == browser->profile()) + return; + } + auto it = registrations_.find(context_id); + // We cannot delete immediately here: the profile might still be referenced + // during the browser tier-down process. + base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, + it->second.release()); + registrations_.erase(it); + std::move(pending_disposal->second).Run(true, ""); + pending_context_disposals_.erase(pending_disposal); + if (pending_context_disposals_.empty()) + BrowserList::RemoveObserver(this); +} diff --git a/chrome/browser/devtools/devtools_browser_context_manager.h b/chrome/browser/devtools/devtools_browser_context_manager.h new file mode 100644 index 00000000000000..6fdaaca584e4ad --- /dev/null +++ b/chrome/browser/devtools/devtools_browser_context_manager.h @@ -0,0 +1,43 @@ +// Copyright 2018 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_DEVTOOLS_DEVTOOLS_BROWSER_CONTEXT_MANAGER_H_ +#define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_BROWSER_CONTEXT_MANAGER_H_ + +#include "base/memory/weak_ptr.h" +#include "base/no_destructor.h" +#include "chrome/browser/media/router/presentation/independent_otr_profile_manager.h" +#include "content/public/browser/devtools_manager_delegate.h" + +class DevToolsBrowserContextManager : public BrowserListObserver { + public: + static DevToolsBrowserContextManager& GetInstance(); + + Profile* GetProfileById(const std::string& browser_context_id); + std::vector GetBrowserContexts(); + content::BrowserContext* CreateBrowserContext(); + void DisposeBrowserContext( + content::BrowserContext* context, + content::DevToolsManagerDelegate::DisposeCallback callback); + + private: + friend class base::NoDestructor; + DevToolsBrowserContextManager(); + ~DevToolsBrowserContextManager() override; + void OnOriginalProfileDestroyed(Profile* profile); + + void OnBrowserRemoved(Browser* browser) override; + + base::flat_map< + std::string, + std::unique_ptr> + registrations_; + base::flat_map + pending_context_disposals_; + + base::WeakPtrFactory weak_factory_; + DISALLOW_COPY_AND_ASSIGN(DevToolsBrowserContextManager); +}; + +#endif // CHROME_BROWSER_DEVTOOLS_DEVTOOLS_BROWSER_CONTEXT_MANAGER_H_ diff --git a/chrome/browser/devtools/inspector_protocol_config.json b/chrome/browser/devtools/inspector_protocol_config.json index 38dfa64c028e34..923fea67431f3f 100644 --- a/chrome/browser/devtools/inspector_protocol_config.json +++ b/chrome/browser/devtools/inspector_protocol_config.json @@ -18,8 +18,7 @@ }, { "domain": "Target", - "include": [ "setRemoteLocations", "createBrowserContext", "getBrowserContexts", "createTarget", "disposeBrowserContext" ], - "async": ["disposeBrowserContext"], + "include": [ "setRemoteLocations", "createTarget" ], "include_events": [] }, { diff --git a/chrome/browser/devtools/protocol/target_handler.cc b/chrome/browser/devtools/protocol/target_handler.cc index f5c62726504499..84c56145490484 100644 --- a/chrome/browser/devtools/protocol/target_handler.cc +++ b/chrome/browser/devtools/protocol/target_handler.cc @@ -5,151 +5,13 @@ #include "chrome/browser/devtools/protocol/target_handler.h" #include "chrome/browser/devtools/chrome_devtools_manager_delegate.h" +#include "chrome/browser/devtools/devtools_browser_context_manager.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_navigator.h" #include "content/public/browser/devtools_agent_host.h" -namespace { - -class DevToolsBrowserContextManager : public BrowserListObserver { - public: - DevToolsBrowserContextManager(); - protocol::Response CreateBrowserContext(std::string* out_context_id); - protocol::Response GetBrowserContexts( - std::unique_ptr>* browser_context_ids); - Profile* GetBrowserContext(const std::string& context_id); - void DisposeBrowserContext( - const std::string& context_id, - std::unique_ptr callback); - - private: - void OnOriginalProfileDestroyed(Profile* profile); - - void OnBrowserRemoved(Browser* browser) override; - - base::flat_map< - std::string, - std::unique_ptr> - registrations_; - base::flat_map> - pending_context_disposals_; - - base::WeakPtrFactory weak_factory_; - DISALLOW_COPY_AND_ASSIGN(DevToolsBrowserContextManager); -}; - -DevToolsBrowserContextManager::DevToolsBrowserContextManager() - : weak_factory_(this) {} - -Profile* DevToolsBrowserContextManager::GetBrowserContext( - const std::string& context_id) { - auto it = registrations_.find(context_id); - return it == registrations_.end() ? nullptr : it->second->profile(); -} - -protocol::Response DevToolsBrowserContextManager::CreateBrowserContext( - std::string* out_context_id) { - Profile* original_profile = - ProfileManager::GetActiveUserProfile()->GetOriginalProfile(); - - auto registration = - IndependentOTRProfileManager::GetInstance()->CreateFromOriginalProfile( - original_profile, - base::BindOnce( - &DevToolsBrowserContextManager::OnOriginalProfileDestroyed, - weak_factory_.GetWeakPtr())); - *out_context_id = registration->profile()->UniqueId(); - registrations_[*out_context_id] = std::move(registration); - return protocol::Response::OK(); -} - -protocol::Response DevToolsBrowserContextManager::GetBrowserContexts( - std::unique_ptr>* browser_context_ids) { - *browser_context_ids = std::make_unique>(); - for (const auto& registration_pair : registrations_) { - (*browser_context_ids) - ->addItem(registration_pair.second->profile()->UniqueId()); - } - return protocol::Response::OK(); -} - -void DevToolsBrowserContextManager::DisposeBrowserContext( - const std::string& context_id, - std::unique_ptr callback) { - if (pending_context_disposals_.find(context_id) != - pending_context_disposals_.end()) { - callback->sendFailure(protocol::Response::Error( - "Disposal of browser context " + context_id + " is already pending")); - return; - } - auto it = registrations_.find(context_id); - if (it == registrations_.end()) { - callback->sendFailure(protocol::Response::InvalidParams( - "Failed to find browser context with id " + context_id)); - return; - } - - Profile* profile = it->second->profile(); - bool has_opened_browser = false; - for (auto* opened_browser : *BrowserList::GetInstance()) { - if (opened_browser->profile() == profile) { - has_opened_browser = true; - break; - } - } - - // If no browsers are opened - dispose right away. - if (!has_opened_browser) { - registrations_.erase(it); - callback->sendSuccess(); - return; - } - - if (pending_context_disposals_.empty()) - BrowserList::AddObserver(this); - - pending_context_disposals_[context_id] = std::move(callback); - BrowserList::CloseAllBrowsersWithIncognitoProfile( - profile, base::DoNothing(), base::DoNothing(), - true /* skip_beforeunload */); -} - -void DevToolsBrowserContextManager::OnOriginalProfileDestroyed( - Profile* profile) { - base::EraseIf(registrations_, [&profile](const auto& it) { - return it.second->profile()->GetOriginalProfile() == profile; - }); -} - -void DevToolsBrowserContextManager::OnBrowserRemoved(Browser* browser) { - std::string context_id = browser->profile()->UniqueId(); - auto pending_disposal = pending_context_disposals_.find(context_id); - if (pending_disposal == pending_context_disposals_.end()) - return; - for (auto* opened_browser : *BrowserList::GetInstance()) { - if (opened_browser->profile() == browser->profile()) - return; - } - auto it = registrations_.find(context_id); - // We cannot delete immediately here: the profile might still be referenced - // during the browser tier-down process. - base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, - it->second.release()); - registrations_.erase(it); - pending_disposal->second->sendSuccess(); - pending_context_disposals_.erase(pending_disposal); - if (pending_context_disposals_.empty()) - BrowserList::RemoveObserver(this); -} - -base::LazyInstance::Leaky - g_devtools_browser_context_manager; - -} // namespace - TargetHandler::TargetHandler(protocol::UberDispatcher* dispatcher) { protocol::Target::Dispatcher::wire(dispatcher, this); } @@ -192,7 +54,7 @@ protocol::Response TargetHandler::CreateTarget( if (browser_context_id.isJust()) { std::string profile_id = browser_context_id.fromJust(); profile = - g_devtools_browser_context_manager.Get().GetBrowserContext(profile_id); + DevToolsBrowserContextManager::GetInstance().GetProfileById(profile_id); if (!profile) { return protocol::Response::Error( "Failed to find browser context with id " + profile_id); @@ -227,22 +89,4 @@ protocol::Response TargetHandler::CreateTarget( return protocol::Response::OK(); } -protocol::Response TargetHandler::CreateBrowserContext( - std::string* out_context_id) { - return g_devtools_browser_context_manager.Get().CreateBrowserContext( - out_context_id); -} - -protocol::Response TargetHandler::GetBrowserContexts( - std::unique_ptr>* browser_context_ids) { - return g_devtools_browser_context_manager.Get().GetBrowserContexts( - browser_context_ids); -} - -void TargetHandler::DisposeBrowserContext( - const std::string& context_id, - std::unique_ptr callback) { - g_devtools_browser_context_manager.Get().DisposeBrowserContext( - context_id, std::move(callback)); -} diff --git a/chrome/browser/devtools/protocol/target_handler.h b/chrome/browser/devtools/protocol/target_handler.h index e9933b095b6d4a..23f580c1dbd7d6 100644 --- a/chrome/browser/devtools/protocol/target_handler.h +++ b/chrome/browser/devtools/protocol/target_handler.h @@ -28,7 +28,6 @@ class TargetHandler : public protocol::Target::Backend { protocol::Response SetRemoteLocations( std::unique_ptr> in_locations) override; - protocol::Response CreateBrowserContext(std::string* out_context_id) override; protocol::Response CreateTarget( const std::string& url, protocol::Maybe width, @@ -36,12 +35,6 @@ class TargetHandler : public protocol::Target::Backend { protocol::Maybe browser_context_id, protocol::Maybe enable_begin_frame_control, std::string* out_target_id) override; - protocol::Response GetBrowserContexts( - std::unique_ptr>* browser_context_ids) - override; - void DisposeBrowserContext( - const std::string& context_id, - std::unique_ptr callback) override; private: RemoteLocations remote_locations_; diff --git a/content/browser/devtools/protocol/target_handler.cc b/content/browser/devtools/protocol/target_handler.cc index 46cd268c2dd990..f24ac4f28e225f 100644 --- a/content/browser/devtools/protocol/target_handler.cc +++ b/content/browser/devtools/protocol/target_handler.cc @@ -644,19 +644,6 @@ Response TargetHandler::ExposeDevToolsProtocol( return Response::OK(); } -Response TargetHandler::CreateBrowserContext(std::string* out_context_id) { - return Response::Error("Not supported"); -} - -Response TargetHandler::DisposeBrowserContext(const std::string& context_id) { - return Response::Error("Not supported"); -} - -Response TargetHandler::GetBrowserContexts( - std::unique_ptr>* browser_context_ids) { - return Response::Error("Not supported"); -} - Response TargetHandler::CreateTarget(const std::string& url, Maybe width, Maybe height, @@ -733,5 +720,67 @@ void TargetHandler::DevToolsAgentHostCrashed(DevToolsAgentHost* host, : 0); } +protocol::Response TargetHandler::CreateBrowserContext( + std::string* out_context_id) { + DevToolsManagerDelegate* delegate = + DevToolsManager::GetInstance()->delegate(); + if (!delegate) + return Response::Error("Browser context management is not supported."); + BrowserContext* context = delegate->CreateBrowserContext(); + if (!context) + return Response::Error("Failed to create browser context."); + *out_context_id = context->UniqueId(); + return protocol::Response::OK(); +} + +protocol::Response TargetHandler::GetBrowserContexts( + std::unique_ptr>* browser_context_ids) { + DevToolsManagerDelegate* delegate = + DevToolsManager::GetInstance()->delegate(); + if (!delegate) + return Response::Error("Browser context management is not supported."); + std::vector contexts = + delegate->GetBrowserContexts(); + *browser_context_ids = std::make_unique>(); + for (auto* context : contexts) + (*browser_context_ids)->addItem(context->UniqueId()); + return protocol::Response::OK(); +} + +void TargetHandler::DisposeBrowserContext( + const std::string& context_id, + std::unique_ptr callback) { + DevToolsManagerDelegate* delegate = + DevToolsManager::GetInstance()->delegate(); + if (!delegate) { + callback->sendFailure(protocol::Response::Error( + "Browser context management is not supported.")); + return; + } + std::vector contexts = + delegate->GetBrowserContexts(); + auto context_it = + std::find_if(contexts.begin(), contexts.end(), + [&context_id](content::BrowserContext* context) { + return context->UniqueId() == context_id; + }); + if (context_it == contexts.end()) { + callback->sendFailure(protocol::Response::Error( + "Failed to find context with id " + context_id)); + return; + } + delegate->DisposeBrowserContext( + *context_it, + base::BindOnce( + [](std::unique_ptr callback, + bool success, const std::string& error) { + if (success) + callback->sendSuccess(); + else + callback->sendFailure(protocol::Response::Error(error)); + }, + std::move(callback))); +} + } // namespace protocol } // namespace content diff --git a/content/browser/devtools/protocol/target_handler.h b/content/browser/devtools/protocol/target_handler.h index 69b17b4e796415..06a9bbb9ca52b1 100644 --- a/content/browser/devtools/protocol/target_handler.h +++ b/content/browser/devtools/protocol/target_handler.h @@ -71,7 +71,9 @@ class TargetHandler : public DevToolsDomainHandler, Response ExposeDevToolsProtocol(const std::string& target_id, Maybe binding_name) override; Response CreateBrowserContext(std::string* out_context_id) override; - Response DisposeBrowserContext(const std::string& context_id) override; + void DisposeBrowserContext( + const std::string& context_id, + std::unique_ptr callback) override; Response GetBrowserContexts( std::unique_ptr>* browser_context_ids) override; Response CreateTarget(const std::string& url, diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json index 37467634890fe2..72482e3df295cc 100644 --- a/content/browser/devtools/protocol_config.json +++ b/content/browser/devtools/protocol_config.json @@ -77,7 +77,8 @@ "async": ["getInfo"] }, { - "domain": "Target" + "domain": "Target", + "async": ["disposeBrowserContext"] }, { "domain": "Tethering", diff --git a/content/public/browser/devtools_manager_delegate.cc b/content/public/browser/devtools_manager_delegate.cc index 8c63bec9a3cd6e..c53227b4eb2bb6 100644 --- a/content/public/browser/devtools_manager_delegate.cc +++ b/content/public/browser/devtools_manager_delegate.cc @@ -36,6 +36,20 @@ scoped_refptr DevToolsManagerDelegate::CreateNewTarget( return nullptr; } +std::vector +DevToolsManagerDelegate::GetBrowserContexts() { + return std::vector(); +} + +content::BrowserContext* DevToolsManagerDelegate::CreateBrowserContext() { + return nullptr; +} + +void DevToolsManagerDelegate::DisposeBrowserContext(BrowserContext*, + DisposeCallback callback) { + std::move(callback).Run(false, "Browser Context disposal is not supported"); +} + void DevToolsManagerDelegate::ClientAttached(DevToolsAgentHost* agent_host, DevToolsAgentHostClient* client) {} void DevToolsManagerDelegate::ClientDetached(DevToolsAgentHost* agent_host, diff --git a/content/public/browser/devtools_manager_delegate.h b/content/public/browser/devtools_manager_delegate.h index 159824883627e8..93aa28894f4595 100644 --- a/content/public/browser/devtools_manager_delegate.h +++ b/content/public/browser/devtools_manager_delegate.h @@ -46,6 +46,19 @@ class CONTENT_EXPORT DevToolsManagerDelegate { // Creates new inspectable target given the |url|. virtual scoped_refptr CreateNewTarget(const GURL& url); + // Get all live browser contexts created by CreateBrowserContext() method. + virtual std::vector GetBrowserContexts(); + + // May return null if not supported or not possible. Delegate must take + // ownership of the created browser context, and may destroy it at will. + virtual BrowserContext* CreateBrowserContext(); + + // Dispose browser context that was created with |CreateBrowserContext| + // method. + using DisposeCallback = base::OnceCallback; + virtual void DisposeBrowserContext(BrowserContext* context, + DisposeCallback callback); + // Called when a new client is attached/detached. virtual void ClientAttached(DevToolsAgentHost* agent_host, DevToolsAgentHostClient* client); diff --git a/headless/lib/browser/headless_devtools_manager_delegate.cc b/headless/lib/browser/headless_devtools_manager_delegate.cc index e61d50b16cb581..d5050e5fafd8c0 100644 --- a/headless/lib/browser/headless_devtools_manager_delegate.cc +++ b/headless/lib/browser/headless_devtools_manager_delegate.cc @@ -72,4 +72,40 @@ void HeadlessDevToolsManagerDelegate::ClientDetached( sessions_.erase(client); } +std::vector +HeadlessDevToolsManagerDelegate::GetBrowserContexts() { + std::vector contexts; + for (auto* context : browser_->GetAllBrowserContexts()) { + if (context != browser_->GetDefaultBrowserContext()) + contexts.push_back(HeadlessBrowserContextImpl::From(context)); + } + return contexts; +} + +content::BrowserContext* +HeadlessDevToolsManagerDelegate::CreateBrowserContext() { + auto builder = browser_->CreateBrowserContextBuilder(); + builder.SetIncognitoMode(true); + HeadlessBrowserContext* browser_context = builder.Build(); + return HeadlessBrowserContextImpl::From(browser_context); +} + +void HeadlessDevToolsManagerDelegate::DisposeBrowserContext( + content::BrowserContext* browser_context, + DisposeCallback callback) { + HeadlessBrowserContextImpl* context = + HeadlessBrowserContextImpl::From(browser_context); + std::vector web_contents = context->GetAllWebContents(); + while (!web_contents.empty()) { + for (auto* wc : web_contents) + wc->Close(); + // Since HeadlessWebContents::Close spawns a nested run loop to await + // closing, new web_contents could be opened. We need to re-query pages and + // close them too. + web_contents = context->GetAllWebContents(); + } + context->Close(); + std::move(callback).Run(true, ""); +} + } // namespace headless diff --git a/headless/lib/browser/headless_devtools_manager_delegate.h b/headless/lib/browser/headless_devtools_manager_delegate.h index 51e7f34723bf55..50c2c9d60bc77a 100644 --- a/headless/lib/browser/headless_devtools_manager_delegate.h +++ b/headless/lib/browser/headless_devtools_manager_delegate.h @@ -43,6 +43,11 @@ class HeadlessDevToolsManagerDelegate void ClientDetached(content::DevToolsAgentHost* agent_host, content::DevToolsAgentHostClient* client) override; + std::vector GetBrowserContexts() override; + content::BrowserContext* CreateBrowserContext() override; + void DisposeBrowserContext(content::BrowserContext* context, + DisposeCallback callback) override; + private: base::WeakPtr browser_; std::mapCreateBrowserContextBuilder(); - builder.SetIncognitoMode(true); - HeadlessBrowserContext* browser_context = builder.Build(); - - *out_context_id = browser_context->Id(); - return Response::OK(); -} - -Response TargetHandler::DisposeBrowserContext(const std::string& context_id) { - HeadlessBrowserContext* context = - browser()->GetBrowserContextForId(context_id); - - if (!context) - return Response::InvalidParams("browserContextId"); - - std::vector web_contents = context->GetAllWebContents(); - while (!web_contents.empty()) { - for (auto* wc : web_contents) - wc->Close(); - // Since HeadlessWebContents::Close spawns a nested run loop to await - // closing, new web_contents could be opened. We need to re-query pages and - // close them too. - web_contents = context->GetAllWebContents(); - } - context->Close(); - return Response::OK(); -} - -Response TargetHandler::GetBrowserContexts( - std::unique_ptr>* browser_context_ids) { - *browser_context_ids = std::make_unique>(); - for (auto* context : browser()->GetAllBrowserContexts()) { - if (context != browser()->GetDefaultBrowserContext()) - (*browser_context_ids)->addItem(context->Id()); - } - return Response::OK(); -} - } // namespace protocol } // namespace headless diff --git a/headless/lib/browser/protocol/target_handler.h b/headless/lib/browser/protocol/target_handler.h index fa57d8b01c85de..c1b1a250491621 100644 --- a/headless/lib/browser/protocol/target_handler.h +++ b/headless/lib/browser/protocol/target_handler.h @@ -27,11 +27,6 @@ class TargetHandler : public DomainHandler, public Target::Backend { std::string* out_target_id) override; Response CloseTarget(const std::string& target_id, bool* out_success) override; - Response CreateBrowserContext(std::string* out_context_id) override; - Response DisposeBrowserContext(const std::string& context_id) override; - Response GetBrowserContexts( - std::unique_ptr>* browser_context_ids) - override; private: DISALLOW_COPY_AND_ASSIGN(TargetHandler); diff --git a/headless/protocol_config.json b/headless/protocol_config.json index f441c0cff9a326..80fc13a2c4e28a 100644 --- a/headless/protocol_config.json +++ b/headless/protocol_config.json @@ -12,7 +12,7 @@ "options": [ { "domain": "Target", - "include": ["createTarget", "closeTarget", "getBrowserContexts", "createBrowserContext", "disposeBrowserContext"], + "include": ["createTarget", "closeTarget"], "include_events": [] }, {