[discard] Ensure FrameTree::Discard clears service workers
This CL ensures that any service workers registered against a discarded RenderFrameHostImpl are cleared following the a discard operation. Previously service workers were not being cleared as expected because the commit params used to commit the new empty document for discard copied over the service worker network provider in DocumentLoader::CreateWebNavigationParamsToCloneDocument() [1]. As a result service workers could persist for the discarded frame in the case the associated process was not proactively shut down. This CL addresses this by clearing the ServiceWorkerNetworkProvider when a discarded document is installed. This breaks the container host pipe with the browser and the ServiceWorkerClient is destroyed [2]. The ServiceWorkerNetworkProviderForFrame class lives in //content/ and must be replaced with ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance() instead of being nullified in blink as the network provider is expected to be not-null, see [3]. [1] https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/loader/document_loader.cc;l=743;drc=492dc9719f6e1845f4f5c0553cd5c7651115f671 [2] https://source.chromium.org/chromium/chromium/src/+/main:content/browser/service_worker/service_worker_context_core.cc;l=527;drc=492dc9719f6e1845f4f5c0553cd5c7651115f671 [3] https://source.chromium.org/chromium/chromium/src/+/main:content/renderer/render_frame_impl.cc;l=3045;drc=4c6d5b3c3ed16fa75258c6b4763188f840cb433d Bug: 404877558 Change-Id: If0d495b94d4b5be38f2832152437a4b460f63692 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6367564 Reviewed-by: Rakina Zata Amni <rakina@chromium.org> Reviewed-by: Daniel Cheng <dcheng@chromium.org> Commit-Queue: Tom Lukaszewicz <tluk@chromium.org> Cr-Commit-Position: refs/heads/main@{#1436434}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
10bc435ad0
commit
bbd83a20cf
content
browser
renderer_host
renderer
service_worker
third_party/blink
@ -477,6 +477,31 @@ IN_PROC_BROWSER_TEST_P(FrameTreeBrowserWithDiscardTest,
|
||||
base::test::RunUntil([&]() { return 0u == root->child_count(); }));
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_P(FrameTreeBrowserWithDiscardTest,
|
||||
DiscardClearsServiceWorkers) {
|
||||
WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
|
||||
FrameTree& frame_tree = wc->GetPrimaryFrameTree();
|
||||
FrameTreeNode* root = frame_tree.root();
|
||||
|
||||
// Load a new page, register a service worker and wait for it to become ready.
|
||||
EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL(
|
||||
"/register_service_worker.html")));
|
||||
EXPECT_EQ("DONE", EvalJs(shell(), "register('/fetch_event_passthrough.js')"));
|
||||
RenderFrameHostImplWrapper rfh(wc->GetPrimaryMainFrame());
|
||||
EXPECT_EQ(1u, rfh->service_worker_clients_for_testing().size());
|
||||
|
||||
// Discard the frame tree.
|
||||
EXPECT_FALSE(root->was_discarded());
|
||||
EXPECT_FALSE(wc->GetController().NeedsReload());
|
||||
DiscardFrameTree(frame_tree);
|
||||
EXPECT_TRUE(root->was_discarded());
|
||||
EXPECT_TRUE(wc->GetController().NeedsReload());
|
||||
|
||||
// Assert the service worker has been de-registered post discard.
|
||||
ASSERT_TRUE(base::test::RunUntil(
|
||||
[&]() { return rfh->service_worker_clients_for_testing().size() == 0; }));
|
||||
}
|
||||
|
||||
// Runs pending navigation discard browsertests with RenderDocument enabled for
|
||||
// all frames to ensure a speculative RFH is created during navigation.
|
||||
class FrameTreeDiscardPendingNavigationTest
|
||||
|
@ -3261,6 +3261,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
|
||||
bool AncestorsAllowSameSiteNoneCookiesOverride(
|
||||
const url::Origin& frame_origin) const;
|
||||
|
||||
const std::map<std::string, base::WeakPtr<ServiceWorkerClient>>&
|
||||
service_worker_clients_for_testing() const {
|
||||
return service_worker_clients_;
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class RenderFrameHostFactory;
|
||||
|
||||
|
@ -35,10 +35,15 @@ class ServiceWorkerNetworkProviderForFrame::NewDocumentObserver
|
||||
render_frame()->GetWebFrame()->GetDocumentLoader();
|
||||
DCHECK_EQ(owner_, web_loader->GetServiceWorkerNetworkProvider());
|
||||
|
||||
if (web_frame->GetSecurityOrigin().IsOpaque()) {
|
||||
if (web_frame->GetSecurityOrigin().IsOpaque() ||
|
||||
web_loader->IsForDiscard()) {
|
||||
// At navigation commit we thought the document was eligible to use
|
||||
// service workers so created the network provider, but it turns out it is
|
||||
// not eligible because it is CSP sandboxed.
|
||||
// In the case a frame navigation was committed and the document was
|
||||
// eligible to use service workers, a network provider would have been
|
||||
// created. However once the frame has been discarded and the
|
||||
// corresponding empty document installed it is no longer eligible.
|
||||
web_loader->SetServiceWorkerNetworkProvider(
|
||||
ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance());
|
||||
// |this| and its owner are destroyed.
|
||||
|
@ -147,6 +147,11 @@ class BLINK_EXPORT WebDocumentLoader {
|
||||
// an initial empty document.
|
||||
virtual bool HasLoadedNonInitialEmptyDocument() const = 0;
|
||||
|
||||
// Returns whether the navigation associated with this datasource is for a
|
||||
// frame discard operation, performed with the intention to clear away
|
||||
// associated resources.
|
||||
virtual bool IsForDiscard() const = 0;
|
||||
|
||||
protected:
|
||||
~WebDocumentLoader() = default;
|
||||
};
|
||||
|
@ -3889,6 +3889,10 @@ bool DocumentLoader::HasLoadedNonInitialEmptyDocument() const {
|
||||
return GetFrameLoader().HasLoadedNonInitialEmptyDocument();
|
||||
}
|
||||
|
||||
bool DocumentLoader::IsForDiscard() const {
|
||||
return commit_reason_ == CommitReason::kDiscard;
|
||||
}
|
||||
|
||||
// static
|
||||
void DocumentLoader::DisableCodeCacheForTesting() {
|
||||
GetDisableCodeCacheForTesting() = true;
|
||||
|
@ -218,6 +218,7 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
|
||||
return origin_calculation_debug_info_;
|
||||
}
|
||||
bool HasLoadedNonInitialEmptyDocument() const override;
|
||||
bool IsForDiscard() const override;
|
||||
|
||||
MHTMLArchive* Archive() const { return archive_.Get(); }
|
||||
|
||||
|
Reference in New Issue
Block a user