Skip to content

Commit

Permalink
Document best practices for lifetime management of WebContents / Profile
Browse files Browse the repository at this point in the history
The best practices have been gathered from
https://groups.google.com/a/chromium.org/g/content-owners/c/B0YGJc3A_Ys/m/nvZ5Kw9PEQAJ

Bug: 1376879
Change-Id: I45f784db051a8ebfc9933a25c5189effd261ed3f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4111770
Reviewed-by: Charlie Reis <creis@chromium.org>
Commit-Queue: Łukasz Anforowicz <lukasza@chromium.org>
Reviewed-by: David Roger <droger@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1085058}
  • Loading branch information
anforowicz authored and Chromium LUCI CQ committed Dec 19, 2022
1 parent cb9f237 commit 16eddbc
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 2 deletions.
44 changes: 44 additions & 0 deletions chrome/browser/profiles/README.md
@@ -0,0 +1,44 @@
# Managing lifetime of a Profile

## KeyedService::Shutdown

If a `KeyedService` owns objects that depend on the lifetime of its `Profile` then it
needs to ensure that these objects are destroyed before the `Profile` is
destroyed (e.g. `content::WebContents` need to be be destroyed before their
`Profile` is destroyed). This can be done by overriding
`KeyedService::Shutdown` - this method will be called before the `Profile` object
is destroyed.

## ScopedProfileKeepAlive

Typically, closing the last `Browser` window associated with a `Profile` will
start tearing down the `Profile`. This is undesirable if there are
`content::WebContents` associated with that `Profile` in standalone (i.e.
non-`Browser`) windows that shouldn't go away without an explicit user action to
close such a window. In such cases, `Profile` destruction can be postponed by
holding ` ScopedProfileKeepAlive`.

`ScopedProfileKeepAlive` is a strong reference to a `Profile` object.
It is very similar to `ScopedKeepAlive`, which is for the browser process.

## BrowserContextKeyedServiceShutdownNotifierFactory

If an object is not a `KeyedService`, but still needs to react to destruction of
a specific `KeyedService`, then it can do so using
`BrowserContextKeyedServiceShutdownNotifierFactory`.

For example, `extensions::ExtensionURLLoaderFactory` is owned by its remote mojo
client (i.e. it is not a `KeyedService`) but it still wants to avoid processing
further `chrome-extension://` resource requests after `Profile` destruction.
This is done by
[registering](https://source.chromium.org/chromium/chromium/src/+/main:extensions/browser/extension_protocols.cc;l=954-959;drc=d632a0e263747345842d2a01f43179d711c4a5d4)
`ExtensionURLLoaderFactory::OnBrowserContextDestroyed` to be called
[when extension-related keyed services get
destroyed](https://source.chromium.org/chromium/chromium/src/+/main:extensions/browser/extension_protocols.cc;l=1008-1009;drc=d632a0e263747345842d2a01f43179d711c4a5d4).

## Only when necessary: ProfileObserver::OnProfileWillBeDestroyed

If you *really* need to directly listen for Profile destruction you can use
`ProfileObserver::OnProfileWillBeDestroyed`, but in general if you need this,
it's a bad sign, as it means that you're using a feature that is not properly
encapsulated in a keyed service.
4 changes: 4 additions & 0 deletions chrome/browser/profiles/keep_alive/README.md
Expand Up @@ -3,3 +3,7 @@
`ScopedProfileKeepAlive` is a strong reference to a `Profile` object, which is
refcounted when the DestroyProfileOnBrowserClose flag is enabled. It is very
similar to `ScopedKeepAlive`, which is for the browser process.

For other best practices related to managing the lifetime of a `Profile`,
please see the "Managing lifetime of a Profile" section in
//chrome/browser/profiles/README.md.
10 changes: 8 additions & 2 deletions content/public/browser/web_contents.h
Expand Up @@ -271,10 +271,16 @@ class WebContents : public PageNavigator,
//
// The caller is responsible for ensuring that the returned WebContents is
// destroyed (e.g. closed) *before* the BrowserContext associated with
// `params` is destroyed. It is a bug if WebContents haven't been destroyed
// when the destructor of BrowserContext starts running. It is not
// `params` is destroyed. It is a security bug if WebContents haven't been
// destroyed when the destructor of BrowserContext starts running. It is not
// necessarily a bug if WebContents haven't been destroyed when
// BrowserContext::NotifyWillBeDestroyed starts running.
//
// Best practices for managing the lifetime of `WebContents` and
// `BrowserContext` will vary across different //content embedders. For
// example, for information specific to the //chrome layer, please see the
// "Managing lifetime of a Profile" section in
// //chrome/browser/profiles/README.md.
CONTENT_EXPORT static std::unique_ptr<WebContents> Create(
const CreateParams& params);

Expand Down

0 comments on commit 16eddbc

Please sign in to comment.