Commit bec31272 authored by arthursonzogni's avatar arthursonzogni Committed by Commit Bot

bfcache: Disable for WebUSB.

A page using the WebUSB API shouldn't be frozen and shouldn't enter the
BackForwardCache.

When navigating away from a page:
 1) The USB connection should be released.
 2) The tab indicator should be removed.

This won't happen if the RenderFrameHost is kept in the back-forward
cache.

Some background on why we sometimes need to disable bfcache:
https://docs.google.com/document/d/1NjZeusdS1kyEkZyfLggndU1A6qVt0Y1sa-LRUxnMoK8

Bug: 1001087
Change-Id: I17a860433f353f2371ebb223791492317a6897ab
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1837933Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Reviewed-by: default avatarAlex Moshchuk <alexmos@chromium.org>
Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704144}
parent f62ebc4f
......@@ -17,6 +17,7 @@
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
......@@ -2638,4 +2639,96 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTestWithDomainControlEnabled,
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
delete_observer_rfh_b.WaitUntilDeleted();
}
// Check the BackForwardCache is disabled when the WebUSB feature is used.
IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, WebUSB) {
// WebUSB requires HTTPS.
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.AddDefaultHandlers(GetTestDataFilePath());
https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
ASSERT_TRUE(https_server.Start());
// Main document.
{
content::BackForwardCacheDisabledTester tester;
GURL url(https_server.GetURL("a.com", "/title1.html"));
EXPECT_TRUE(NavigateToURL(shell(), url));
EXPECT_FALSE(current_frame_host()->is_back_forward_cache_disallowed());
EXPECT_EQ("Found 0 devices", content::EvalJs(current_frame_host(), R"(
new Promise(async resolve => {
let devices = await navigator.usb.getDevices();
resolve("Found " + devices.length + " devices");
});
)"));
EXPECT_TRUE(current_frame_host()->is_back_forward_cache_disallowed());
EXPECT_TRUE(tester.IsDisabledForFrameWithReason(
current_frame_host()->GetProcess()->GetID(),
current_frame_host()->GetRoutingID(), "WebUSB"));
}
// Nested document.
{
content::BackForwardCacheDisabledTester tester;
GURL url(
https_server.GetURL("c.com", "/cross_site_iframe_factory.html?c(d)"));
EXPECT_TRUE(NavigateToURL(shell(), url));
RenderFrameHostImpl* rfh_c = current_frame_host();
RenderFrameHostImpl* rfh_d = rfh_c->child_at(0)->current_frame_host();
EXPECT_FALSE(rfh_c->is_back_forward_cache_disallowed());
EXPECT_FALSE(rfh_d->is_back_forward_cache_disallowed());
EXPECT_EQ("Found 0 devices", content::EvalJs(rfh_c, R"(
new Promise(async resolve => {
let devices = await navigator.usb.getDevices();
resolve("Found " + devices.length + " devices");
});
)"));
EXPECT_TRUE(rfh_c->is_back_forward_cache_disallowed());
EXPECT_FALSE(rfh_d->is_back_forward_cache_disallowed());
EXPECT_TRUE(tester.IsDisabledForFrameWithReason(
rfh_c->GetProcess()->GetID(), rfh_c->GetRoutingID(), "WebUSB"));
}
// Worker.
{
content::BackForwardCacheDisabledTester tester;
GURL url(https_server.GetURL("e.com", "/title1.html"));
EXPECT_TRUE(NavigateToURL(shell(), url));
EXPECT_FALSE(current_frame_host()->is_back_forward_cache_disallowed());
EXPECT_EQ("Found 0 devices", content::EvalJs(current_frame_host(), R"(
new Promise(async resolve => {
const worker = new Worker("/back_forward_cache/webusb/worker.js");
worker.onmessage = message => resolve(message.data);
worker.postMessage("Run");
});
)"));
EXPECT_TRUE(current_frame_host()->is_back_forward_cache_disallowed());
EXPECT_TRUE(tester.IsDisabledForFrameWithReason(
current_frame_host()->GetProcess()->GetID(),
current_frame_host()->GetRoutingID(), "WebUSB"));
}
// Nested worker.
{
content::BackForwardCacheDisabledTester tester;
GURL url(https_server.GetURL("f.com", "/title1.html"));
EXPECT_TRUE(NavigateToURL(shell(), url));
EXPECT_FALSE(current_frame_host()->is_back_forward_cache_disallowed());
EXPECT_EQ("Found 0 devices", content::EvalJs(current_frame_host(), R"(
new Promise(async resolve => {
const worker = new Worker(
"/back_forward_cache/webusb/nested-worker.js");
worker.onmessage = message => resolve(message.data);
worker.postMessage("Run");
});
)"));
EXPECT_TRUE(current_frame_host()->is_back_forward_cache_disallowed());
EXPECT_TRUE(tester.IsDisabledForFrameWithReason(
current_frame_host()->GetProcess()->GetID(),
current_frame_host()->GetRoutingID(), "WebUSB"));
}
}
} // namespace content
......@@ -6245,6 +6245,7 @@ void RenderFrameHostImpl::DeleteWebBluetoothService(
void RenderFrameHostImpl::CreateWebUsbService(
mojo::PendingReceiver<blink::mojom::WebUsbService> receiver) {
BackForwardCache::DisableForRenderFrameHost(this, "WebUSB");
GetContentClient()->browser()->CreateWebUsbService(this, std::move(receiver));
}
......
......@@ -360,13 +360,12 @@ void DedicatedWorkerHost::CreateWebUsbService(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHostImpl* ancestor_render_frame_host =
GetAncestorRenderFrameHost();
if (!ancestor_render_frame_host) {
// The ancestor frame may have already been closed. In that case, the worker
// will soon be terminated too, so abort the connection.
// The ancestor frame may have already been closed. In that case, the worker
// will soon be terminated too, so abort the connection.
if (!ancestor_render_frame_host)
return;
}
GetContentClient()->browser()->CreateWebUsbService(ancestor_render_frame_host,
std::move(receiver));
ancestor_render_frame_host->CreateWebUsbService(std::move(receiver));
}
void DedicatedWorkerHost::CreateWebSocketConnector(
......
// Copyright 2019 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.
const worker = new Worker("./worker.js");
// This worker is a simple bidirectional proxy.
onmessage = message => worker.postMessage(message.data);
worker.onmessage = message => postMessage(message.data);
// Copyright 2019 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.
onmessage = async () => {
let devices = await navigator.usb.getDevices();
postMessage("Found " + devices.length + " devices");
}
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