Define and implement ProcessSelectionDeferringCondition API

This CL adds a ProcessSelectionDeferringCondition and
ProcessSelectionDeferringConditionRunner which is modeled after the
existing CommitDeferringCondition API but is invoked at an earlier stage
of the navigation lifecycle. The feature is guarded by a feature flag,
kProcessSelectionDeferringConditions, which is disabled by default. The
first client of this API,
`site_protection::SiteFamiliarityProcessSelectionDeferringCondition`,
is implemented in a subsequent CL ( crrev.com/c/6897186 ).

This makes it possible for some features to toggle their state based on
whether a site is familiar to the user's profile. The services we want
to use in determining site familiarity involve using asynchronous APIs
that introduce delays due to thread switching. To enable these calls,
we're adding a ProcessSelectionDeferringCondition API that allows
clients to be notified at navigation start, on redirect, and before the
process selection is finalized.

The standard ways of observing the navigation flow (WebContentsObserver
and NavigationThrottle) do not work for this use-case because the
settings we need to toggle have to be determined before the renderer
process selection is finalized. Both WebContentsObserver and
NavigationThrottle provide WillProcessResponse() but this handler is
called after the process selection has been finalized. The existing
CommitDeferringCondition mechanism does not work for the same reason --
it also defers after the final process selection is made.

Overview of how the ProcessSelectionDeferringCondition works:

1. A client implements the ProcessSelectionDeferringCondition
   interface and registers in the appropriate embedder by overriding:
   ContentBrowserClient::CreateProcessSelectionDeferringConditionsForNavigation().

2. When a navigation begins, it creates a
   ProcessSelectionDeferringConditionRunner and registers any
   ProcessSelectionDeferringConditions that are provided by the
   ContentClientBrowser. A NavigationHandle is passed into the
   constructor at this time so that deferring conditions may begin work
   on the navigation as soon as they are created.

3. If the navigation is redirected,
   ProcessSelectionDeferringCondition::OnRequestRedirected() is called
   to allow conditions to reset or restart their work.

4. After the network response is received but before a process is
   selected, ProcessSelectionDeferringCondition::OnWillSelectFinalProcess()
   is called. The condition can then:
   * Return Result::kProceed to allow process selection to continue
     synchronously.
   * Return Result::kDefer to pause process selection. The condition
     must then invoke a provided resume closure to resume the
     navigation.

Overview of changes:
   * Define the ProcessSelectionDeferringCondition interface in
     content/public/browser.
   * Implemented ProcessSelectionDeferringConditionRunner to manage the
     running the registered conditions.
   * Integrate the runner into NavigationRequest, calling it at
     redirects and before the final call to
     SelectFrameHostForOnResponseStarted.
   * Add the CreateProcessSelectionDeferringConditionsForNavigation
     API to ContentBrowserClient for embedders to register their
     ProcessSelectionDeferringConditions.
   * Added browser tests and unit tests for the new mechanism.

Change-Id: I5888202e8433c4eb405c2bb85d4e60d4872396ec
Bug: 434009835
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6784549
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
Reviewed-by: Peter Kotwicz <pkotwicz@chromium.org>
Commit-Queue: Javier Castro <jacastro@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1520795}
15 files changed
tree: 77a932d05848ea6ae9e819293f4b670fe8cf60a7
  1. .gemini/
  2. .github/
  3. agents/
  4. android_webview/
  5. apps/
  6. ash/
  7. base/
  8. build/
  9. build_overrides/
  10. buildtools/
  11. cc/
  12. chrome/
  13. chromecast/
  14. chromeos/
  15. codelabs/
  16. components/
  17. content/
  18. crypto/
  19. dbus/
  20. device/
  21. docs/
  22. extensions/
  23. fuchsia_web/
  24. gin/
  25. google_apis/
  26. gpu/
  27. headless/
  28. infra/
  29. ios/
  30. ipc/
  31. media/
  32. mojo/
  33. net/
  34. pdf/
  35. printing/
  36. remoting/
  37. rlz/
  38. sandbox/
  39. services/
  40. skia/
  41. sql/
  42. storage/
  43. styleguide/
  44. testing/
  45. third_party/
  46. tools/
  47. ui/
  48. url/
  49. webkit/
  50. .clang-format
  51. .clang-tidy
  52. .clangd
  53. .cursorignore
  54. .geminiignore
  55. .git-blame-ignore-revs
  56. .gitallowed
  57. .gitattributes
  58. .gitignore
  59. .gitmodules
  60. .gn
  61. .mailmap
  62. .rustfmt.toml
  63. .vpython3
  64. .yapfignore
  65. ATL_OWNERS
  66. AUTHORS
  67. BUILD.gn
  68. CODE_OF_CONDUCT.md
  69. codereview.settings
  70. CPPLINT.cfg
  71. CRYPTO_OWNERS
  72. DEPS
  73. DIR_METADATA
  74. LICENSE
  75. LICENSE.chromium_os
  76. OWNERS
  77. PRESUBMIT.py
  78. PRESUBMIT_test.py
  79. PRESUBMIT_test_mocks.py
  80. README.md
  81. SECURITY_OWNERS
  82. WATCHLISTS
README.md

Logo Chromium

Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all users to experience the web.

The project's web site is https://www.chromium.org.

To check out the source code locally, don't use git clone! Instead, follow the instructions on how to get the code.

Documentation in the source is rooted in docs/README.md.

Learn how to Get Around the Chromium Source Code Directory Structure.

For historical reasons, there are some small top level directories. Now the guidance is that new top level directories are for product (e.g. Chrome, Android WebView, Ash). Even if these products have multiple executables, the code should be in subdirectories of the product.

If you found a bug, please file it at https://crbug.com/new.