Commit d0c9d517 authored by Yury Semikhatsky's avatar Yury Semikhatsky Committed by Commit Bot

[DevTools] Auto-attach to service workers

The change enables top level target handler to auto-attach to service worker
when they are created and pause their execution until runIfWaitingForDebugger
is received from the client. This brings service worker functionality on par
with pages and will enable automation tools to configure a service worker
without attaching to every page that may use it.

Design document: https://docs.google.com/document/d/1hbTowhyfrf6CaYuNEHjY_OVx2KgZmnbp8kg_wUdGFiA/edit#

Bug: 1051687
Change-Id: I24ceb9398bce1ab00afbbe427c508e4fa5a7ead5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2107792
Commit-Queue: Yury Semikhatsky <yurys@chromium.org>
Reviewed-by: default avatarPavel Feldman <pfeldman@chromium.org>
Reviewed-by: default avatarPeter Marshall <petermarshall@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#751417}
parent c12a8725
......@@ -73,8 +73,8 @@ bool BrowserDevToolsAgentHost::AttachSession(DevToolsSession* session) {
session->SetBrowserOnly(true);
session->AddHandler(std::make_unique<protocol::TargetHandler>(
protocol::TargetHandler::AccessMode::kBrowser, GetId(),
GetRendererChannel(), session->GetRootSession()));
protocol::TargetHandler::AccessMode::kBrowser, GetId(), nullptr,
session->GetRootSession()));
if (only_discovery_)
return true;
......
......@@ -262,15 +262,21 @@ void TargetAutoAttacher::ReattachServiceWorkers(bool waiting_for_debugger) {
if (!auto_attaching_service_workers_)
return;
BrowserContext* browser_context = nullptr;
if (render_frame_host_)
browser_context = render_frame_host_->GetProcess()->GetBrowserContext();
auto matching = GetMatchingServiceWorkers(browser_context,
GetFrameUrls(render_frame_host_));
Hosts new_hosts;
for (const auto& pair : matching)
new_hosts.insert(pair.second);
if (is_browser_mode()) {
ServiceWorkerDevToolsAgentHost::List agent_hosts;
ServiceWorkerDevToolsManager::GetInstance()->AddAllAgentHosts(&agent_hosts);
new_hosts.insert(agent_hosts.begin(), agent_hosts.end());
} else {
BrowserContext* browser_context = nullptr;
if (render_frame_host_)
browser_context = render_frame_host_->GetProcess()->GetBrowserContext();
auto matching = GetMatchingServiceWorkers(browser_context,
GetFrameUrls(render_frame_host_));
for (const auto& pair : matching)
new_hosts.insert(pair.second);
}
ReattachTargetsOfType(new_hosts, DevToolsAgentHost::kTypeServiceWorker,
waiting_for_debugger);
}
......@@ -300,7 +306,8 @@ void TargetAutoAttacher::SetAutoAttach(bool auto_attach,
if (auto_attach && !auto_attach_) {
auto_attach_ = true;
auto_attaching_service_workers_ =
render_frame_host_ && !render_frame_host_->GetParent();
is_browser_mode() ||
(render_frame_host_ && !render_frame_host_->GetParent());
if (auto_attaching_service_workers_) {
ServiceWorkerDevToolsManager::GetInstance()->AddObserver(this);
ReattachServiceWorkers(false);
......@@ -322,32 +329,47 @@ void TargetAutoAttacher::SetAutoAttach(bool auto_attach,
false);
DCHECK(auto_attached_hosts_.empty());
}
renderer_channel_->SetReportChildWorkers(
this, auto_attach, wait_for_debugger_on_start, std::move(callback));
if (renderer_channel_) {
renderer_channel_->SetReportChildWorkers(
this, auto_attach, wait_for_debugger_on_start, std::move(callback));
} else {
std::move(callback).Run();
}
}
// -------- ServiceWorkerDevToolsManager::Observer ----------
void TargetAutoAttacher::WorkerCreated(ServiceWorkerDevToolsAgentHost* host,
bool* should_pause_on_start) {
BrowserContext* browser_context = nullptr;
if (render_frame_host_)
browser_context = render_frame_host_->GetProcess()->GetBrowserContext();
auto hosts = GetMatchingServiceWorkers(browser_context,
GetFrameUrls(render_frame_host_));
if (hosts.find(host->GetId()) != hosts.end()) {
if (is_browser_mode()) {
*should_pause_on_start = wait_for_debugger_on_start_;
Hosts new_hosts;
for (const auto& pair : hosts)
new_hosts.insert(pair.second);
ReattachTargetsOfType(new_hosts, DevToolsAgentHost::kTypeServiceWorker,
wait_for_debugger_on_start_);
delegate_->AutoAttach(host, wait_for_debugger_on_start_);
auto_attached_hosts_.insert(host);
} else {
BrowserContext* browser_context = nullptr;
if (render_frame_host_)
browser_context = render_frame_host_->GetProcess()->GetBrowserContext();
auto hosts = GetMatchingServiceWorkers(browser_context,
GetFrameUrls(render_frame_host_));
if (hosts.find(host->GetId()) != hosts.end()) {
*should_pause_on_start = wait_for_debugger_on_start_;
Hosts new_hosts;
for (const auto& pair : hosts)
new_hosts.insert(pair.second);
ReattachTargetsOfType(new_hosts, DevToolsAgentHost::kTypeServiceWorker,
wait_for_debugger_on_start_);
}
}
}
void TargetAutoAttacher::WorkerDestroyed(ServiceWorkerDevToolsAgentHost* host) {
ReattachServiceWorkers(false);
if (is_browser_mode()) {
auto_attached_hosts_.erase(base::WrapRefCounted(host));
delegate_->AutoDetach(host);
} else {
ReattachServiceWorkers(false);
}
}
void TargetAutoAttacher::ChildWorkerCreated(DevToolsAgentHostImpl* agent_host,
......
......@@ -63,6 +63,7 @@ class TargetAutoAttacher : public ServiceWorkerDevToolsManager::Observer {
void WorkerDestroyed(ServiceWorkerDevToolsAgentHost* host) override;
void UpdateFrames();
bool is_browser_mode() const { return !renderer_channel_; }
Delegate* delegate_;
DevToolsRendererChannel* renderer_channel_;
......
Tests that browser.Target.setAutoAttach() attaches to new service workers.
Started and attached to service_worker target, waitingForDebugger=true
self.globalVar = undefined
Resumed, self.globalVar = 2020
(async function(testRunner) {
const {page, session, dp} = await testRunner.startURL(
'/inspector-protocol/resources/empty.html',
`Tests that browser.Target.setAutoAttach() attaches to new service workers.`);
const swHelper = (await testRunner.loadScript('../service-worker/resources/service-worker-helper.js'))(dp, session);
const target = testRunner.browserP().Target;
await Promise.all([
target.setDiscoverTargets({discover: true}),
target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true, flatten: true}),
]);
const swTargetPromises = [
target.onceTargetCreated(),
target.onceAttachedToTarget(),
];
const activatedPromise = swHelper.installSWAndWaitForActivated('/inspector-protocol/service-worker/resources/blank-service-worker.js');
const [swTarget, swAttachedEvent] = await Promise.all(swTargetPromises);
const swTargetInfo = swTarget.params.targetInfo;
testRunner.log(`Started and attached to ${swTargetInfo.type} target, waitingForDebugger=${swAttachedEvent.params.waitingForDebugger}`);
const swSession = new TestRunner.Session(testRunner, swAttachedEvent.params.sessionId);
testRunner.log('self.globalVar = ' + await swSession.evaluate('self.globalVar'));
await Promise.all([
swSession.protocol.Runtime.runIfWaitingForDebugger(),
activatedPromise,
]);
testRunner.log('Resumed, self.globalVar = ' + await swSession.evaluate('self.globalVar'));
testRunner.completeTest();
})
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment