1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "headless/lib/browser/headless_devtools_manager_delegate.h"
#include "base/containers/contains.h"
#include "build/build_config.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_agent_host_client_channel.h"
#include "content/public/browser/web_contents.h"
#include "headless/lib/browser/headless_browser_context_impl.h"
#include "headless/lib/browser/headless_browser_impl.h"
#include "headless/lib/browser/headless_web_contents_impl.h"
#include "headless/lib/browser/protocol/headless_devtools_session.h"
#include "ui/base/resource/resource_bundle.h"
namespace headless {
HeadlessDevToolsManagerDelegate::HeadlessDevToolsManagerDelegate(
base::WeakPtr<HeadlessBrowserImpl> browser)
: browser_(std::move(browser)) {}
HeadlessDevToolsManagerDelegate::~HeadlessDevToolsManagerDelegate() = default;
void HeadlessDevToolsManagerDelegate::HandleCommand(
content::DevToolsAgentHostClientChannel* channel,
base::span<const uint8_t> message,
NotHandledCallback callback) {
auto it = sessions_.find(channel);
CHECK(it != sessions_.end());
it->second->HandleCommand(message, std::move(callback));
}
scoped_refptr<content::DevToolsAgentHost>
HeadlessDevToolsManagerDelegate::CreateNewTarget(
const GURL& url,
content::DevToolsManagerDelegate::TargetType target_type,
bool new_window) {
if (!browser_)
return nullptr;
HeadlessBrowserContext* context = browser_->GetDefaultBrowserContext();
HeadlessWebContentsImpl* web_contents_impl = HeadlessWebContentsImpl::From(
context->CreateWebContentsBuilder()
.SetInitialURL(url)
.SetWindowBounds(gfx::Rect(browser_->options()->window_size))
.Build());
return target_type == content::DevToolsManagerDelegate::kTab
? content::DevToolsAgentHost::GetOrCreateForTab(
web_contents_impl->web_contents())
: content::DevToolsAgentHost::GetOrCreateFor(
web_contents_impl->web_contents());
}
bool HeadlessDevToolsManagerDelegate::HasBundledFrontendResources() {
return true;
}
void HeadlessDevToolsManagerDelegate::ClientAttached(
content::DevToolsAgentHostClientChannel* channel) {
DCHECK(!base::Contains(sessions_, channel));
sessions_.emplace(
channel,
std::make_unique<protocol::HeadlessDevToolsSession>(browser_, channel));
}
void HeadlessDevToolsManagerDelegate::ClientDetached(
content::DevToolsAgentHostClientChannel* channel) {
sessions_.erase(channel);
}
std::vector<content::BrowserContext*>
HeadlessDevToolsManagerDelegate::GetBrowserContexts() {
std::vector<content::BrowserContext*> contexts;
if (!browser_)
return contexts;
for (auto* context : browser_->GetAllBrowserContexts()) {
if (context != browser_->GetDefaultBrowserContext())
contexts.push_back(HeadlessBrowserContextImpl::From(context));
}
return contexts;
}
content::BrowserContext*
HeadlessDevToolsManagerDelegate::GetDefaultBrowserContext() {
return browser_ ? HeadlessBrowserContextImpl::From(
browser_->GetDefaultBrowserContext())
: nullptr;
}
content::BrowserContext*
HeadlessDevToolsManagerDelegate::CreateBrowserContext() {
if (!browser_)
return nullptr;
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<HeadlessWebContents*> 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
|