diff --git a/.gemini/commands/cr/gerrit/cldescription.toml b/.gemini/commands/cr/gerrit/cldescription.toml
index 128ca15..89fff52 100644
--- a/.gemini/commands/cr/gerrit/cldescription.toml
+++ b/.gemini/commands/cr/gerrit/cldescription.toml
@@ -1,26 +1,9 @@
 description="Suggest a CL description"
 prompt = """
-You are a senior software engineer writing a final, human-readable Change List
-(CL) description.
+@{agents/prompts/templates/cldescription.md}
 
 Use `git upstream-diff` to identify the changs applied to a git repository.
 
 Please provide a brief and concise description of the code diff above, which
 can be used as a CL description.
-
-The description consists of two parts:
-
-- The first line should be short, focused, and stand alone. It should not
-  exceed 72 characters in length and stay under 50 characters if possible.
-- The CL description body should include informative details that help
-  reviewers and future code searchers understand the CL's effect. This should be
-  also brief and concise.
-
-You can omit the second part, the CL description body, if the diff is short and
-self-explanatory.
-
-Do not include any links, e.g. to bugs, other CLs, or design docs, just a brief
-description of the code diff.
-
-Do not include CL description tags either, like RELNOTES or TESTED.
 """
diff --git a/.github/README.md b/.github/README.md
index 27c64256..cf597ce 100644
--- a/.github/README.md
+++ b/.github/README.md
@@ -10,15 +10,15 @@
 Copilot.
 
 ## Where is copilot-instructions.md?
-[`copilot-intructions.md`](../copilot-instructions.md) is typically a single
+[`copilot-instructions.md`](../copilot-instructions.md) is typically a single
 instruction file that contains default instructions for a workspace. These
 instructions are automatically included in every chat request.
 
-Until the prompt in `copilot-intructions.md` is generally agreed upon for the
+Until the prompt in `copilot-instructions.md` is generally agreed upon for the
 chromium repo, this file is intentionally excluded from the repo, and added to
 the [.gitignore](../.gitignore) for your customization.
 
-For generating your own `copilot-intructions.md`, type
+For generating your own `copilot-instructions.md`, type
 `/create_copilot_instructions` in GitHub Copilot to get started.
 
 ## Code Layout
@@ -47,10 +47,10 @@
 Use `/git_commit_ghc`
 
 - [.github/instructions](./instructions/): Instructions that are automatically
-  picked up using `applyTo` syntax will have a much higher review bar then those
+  picked up using `applyTo` syntax will have a much higher review bar than those
   without it.
 - [.github/prompts](./prompts/): All prompts should specify a `mode` and
   `description`.
 - [.github/resources](./resources/): All prompt resources should have an active
-  reference or usecase a file in `instructions` or `prompts`, and should be
+  reference or use case in a file in `instructions` or `prompts`, and should be
   cleaned up if their references are modified or removed.
diff --git a/.github/workflows/close-pull-request.yml b/.github/workflows/close-pull-request.yml
new file mode 100644
index 0000000..f527ca7
--- /dev/null
+++ b/.github/workflows/close-pull-request.yml
@@ -0,0 +1,22 @@
+# GitHub actions workflow.
+# https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions
+
+# https://github.com/superbrothers/close-pull-request
+name: Close Pull Request
+
+on:
+  pull_request_target:
+    types: [opened]
+
+jobs:
+  run:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: superbrothers/close-pull-request@v3
+      with:
+        comment: >
+          Thanks for your contribution!
+          Unfortunately, we don't use GitHub pull requests to manage code
+          contributions to this repository.
+          Instead, please see [README.md](../blob/HEAD/docs/contributing.md)
+          which provides full instructions on how to get involved.
diff --git a/DEPS b/DEPS
index 1c4290f..364ce96d 100644
--- a/DEPS
+++ b/DEPS
@@ -240,7 +240,7 @@
   # luci-go CIPD package version.
   # Make sure the revision is uploaded by infra-packagers builder.
   # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console
-  'luci_go': 'git_revision:21504d3595ac903ef60bac732d885cd8e6ed92ba',
+  'luci_go': 'git_revision:f769e04338c2db24c3697f00ede9cadbd3ee7582',
 
   # This can be overridden, e.g. with custom_vars, to build clang from HEAD
   # instead of downloading the prebuilt pinned revision.
@@ -316,11 +316,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'b8acdbdf77d8196d2917ed4e8d8aef8329068904',
+  'v8_revision': '018afda931c627de446796ce6a0d38da3fd038c3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '4e623053ea80f650a2bf207b60d1cd26571b37f6',
+  'angle_revision': 'd5f67f17ee48eed48b6c8ec283646ccbeb0b77ed',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -332,7 +332,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
-  'boringssl_revision': '7d88bb1bf3372bda1134ad8bf624b25b88e0db86',
+  'boringssl_revision': '626a2578ac3e2840d4664562de39d25b1e710a19',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
@@ -376,7 +376,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '9fdb1d4c9d0f278ae34891b069d96ef89ea9cdf2',
+  'catapult_revision': '1ec586469aedb45f1e0809017409346ddf96e210',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling CrossBench
   # and whatever else without interference from each other.
@@ -400,7 +400,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': 'cf4128082e46865c4469211511703c4d4d76ed33',
+  'devtools_frontend_revision': 'a718fd59205c847882992a8aec65f5e23ed93a7c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -424,7 +424,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'd21eb9f4c686880e65d8e6c94e8b0596b09ac435',
+  'dawn_revision': '67a0164c434f43952232554ed1f90369206ff5d1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -436,7 +436,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ink_stroke_modeler
   # and whatever else without interference from each other.
-  'ink_stroke_modeler_revision': 'eb42ec75e79ebde11169519e8c665a8f0c4e1fc3',
+  'ink_stroke_modeler_revision': '3fa5129ed1ae6f8b2ec4e9b60fa5d08cc81e2d78',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -1207,7 +1207,7 @@
       'packages': [
           {
               'package': 'chromium/chrome/android/orderfiles/arm64',
-              'version': 'TwrLw1Z-0Tq1f9EnAQc9juMOSG19Ra6DOU25hzazR-kC',
+              'version': 't3WOzTiHuLGI18PRc5aKJBOSjqRQZBY28yn-F5Q5VPIC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -1229,7 +1229,7 @@
       'packages': [
           {
               'package': 'chromium/android_webview/tools/orderfiles/arm64',
-              'version': 'W36qMiAp0kSgCH5EkvY_y6_T0Zm8wHNabxWoZx4mlPIC',
+              'version': 'ChSEiXIT87IWuWMsa7wTYKffmK_HH1c2JosFmeVp7VUC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -1434,7 +1434,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/updater/chromium_win_arm64',
-          'version': 'version:2@1584005',
+          'version': 'version:2@1585011',
         },
       ],
   },
@@ -1456,7 +1456,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/updater/chromium_win_x86_64',
-          'version': 'version:2@1584030',
+          'version': 'version:2@1585005',
         },
       ],
   },
@@ -1578,7 +1578,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/enterprise_companion/chromium_win_x86_64',
-          'version': 'sdWqTkd1M4bPCqg4M-gdLLohYLOwcCqCEcssv0DgZl4C',
+          'version': '-_OujuAWhp99JrQVo5Ep4qu-dWUGc9W8l0snkLtsSHcC',
         },
       ],
   },
@@ -1626,7 +1626,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '6ee72ff5ecc3b2013b0837ea8c3c3a721b12838b',
+    '1826169221c2df97bc9334bb042069f26774003a',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1726,7 +1726,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'xaK45BLOgiQ39L2Uk63LH-VFziubwYJ15XzCCwHKAo0C',
+          'version': 'mvV9ZifgIOHqOM9xEhhdmQJUTmj0fBmZciH8DOyvG88C',
       },
     ],
     'condition': 'checkout_android and non_git_source',
@@ -2062,7 +2062,7 @@
     Var('chromium_git') + '/chromium/web-tests.git' + '@' + Var('crossbench_web_tests_revision'),
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '8aad2863865f0d0bde8b2eb804b389412f04a38b',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '044f01ae0351fb8a97efce042c93f99d3e95240c',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -2074,7 +2074,7 @@
     Var('chromium_git') + '/external/github.com/jk-jeon/dragonbox.git' + '@' + 'beeeef91cf6fef89a4d4ba5e95d47ca64ccb3a44',
 
   'src/third_party/eigen3/src':
-    Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + 'c4c704e5ddca35c10cca625807a6919654753459',
+    Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + 'd0d70a952766f6b02f449da040141529748ecd30',
 
   'src/third_party/emoji-metadata/src': {
     'url': Var('chromium_git') + '/external/github.com/googlefonts/emoji-metadata' + '@' + '045f146fca682a836e01cd265171312bfb300e06',
@@ -2615,7 +2615,7 @@
     Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
 
   'src/third_party/perfetto':
-    Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + 'ea8d0aaeb1e22f03fa0498c42e3f86f3daf753f2',
+    Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + 'c9609d1e65bcd21014a708c0c8b8df094cd89a0b',
 
   'src/base/tracing/test/data': {
     'bucket': 'perfetto',
@@ -2942,7 +2942,7 @@
     Var('chromium_git') + '/external/github.com/GoogleChromeLabs/text-fragments-polyfill.git' + '@' + 'c036420683f672d685e27415de0a5f5e85bdc23f',
 
   'src/third_party/tflite/src':
-    Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '38dd09551686ad00bc837f383b3a1db282079498',
+    Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '204f897f9a511e62242fcbaac6be5fbbe9e2e245',
   'src/third_party/litert/src':
     Var('chromium_git') + '/external/github.com/google-ai-edge/LiteRT.git' + '@' + '320c13c17b995e7ccd7b8d6560db255d2f994199',
   'src/third_party/turbine/cipd': {
@@ -2956,7 +2956,7 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@911e009961edb6964c8e63db5093d65afd2a002a',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@d3db3d114ff7fb376fd9d02782069bb09846df24',
   'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@e966816ab28ab7cb448d5b33270b43c941b343d4',
   'src/third_party/spirv-cross/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3',
   'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@f88a2d766840fc825af1fc065977953ba1fa4a91',
@@ -2965,7 +2965,7 @@
   'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@b525c3041d4cb8c684eb368e0b527cbd4b7b25ca',
   'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@6a9d187173f2ec4773da1e7e9cae587f6390d817',
   'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@738ec97a3f659dd6469bff3c4078ef981b0a343f',
-  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@a23d066d0e0b4219681be2a248478632d78f26f6',
+  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@92e89050c4d26acbb88682ad912b34a7ae67d5c5',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'cb0597213b0fcb999caa9ed08c2f88dc45eb7d50',
@@ -2999,10 +2999,10 @@
     Var('chromium_git') + '/external/github.com/SeleniumHQ/selenium/py.git' + '@' + '1e954903022e9386b9acf452c24f4458dd4c4fc1',
 
   'src/third_party/webgl/src':
-    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'c01b768bce4a143e152c1870b6ba99ea6267d2b0',
+    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '8fc2a0dff53abfc0cf2c140d8420759b2036cc54',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'b043a4eaef1e6c46e9c79abc381785aadd9ff057',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '21ecca5d71d440d8283069df3fd51263f68c38d7',
 
   'src/third_party/webpagereplay':
     Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'),
@@ -3032,7 +3032,7 @@
   },
 
   'src/third_party/xnnpack/src':
-    Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + 'e8aad3cc4ffb7259c4aab6dfb922bfbef0ef8be0',
+    Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + '066e3e72b05e56441aebaa57c57fad9280d869c8',
 
   'src/third_party/libei/cipd': {
 
@@ -3054,7 +3054,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/linux-amd64',
-          'version': '7VtXoKLR2gQzBX1OOjx0YQI9VWdOzaM_DgH44vQO1boC',
+          'version': 'TEbyFSosIawFAQ0GwImR_dmamYKUtz9flrGWu8Mal40C',
         },
       ],
       'dep_type': 'cipd',
@@ -3064,7 +3064,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/windows-amd64',
-          'version': 'zR-xLwMicOxKme84IVie9uQQ6PNg-0TNovcNcHbUZmAC',
+          'version': 'iJxKsZ-rNAW1iNpEZdNR3t1-spABy6XGdRjIEeApEwYC',
         },
       ],
       'dep_type': 'cipd',
@@ -3075,7 +3075,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/mac-amd64',
-          'version': 'ekPxFfonWAPuyfvAanDlEnRLGDxHP7IMD4KBpUfvFJMC',
+          'version': '7eneeRHPfLnTAuPNWFJG-vzNNKPo4n55RFhFGTfqhYsC',
         },
       ],
       'dep_type': 'cipd',
@@ -3086,7 +3086,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/mac-arm64',
-          'version': 'xD54rz_TXvJfUXFb6tYphj6_CmoP8aoncE0CJoa3KfwC',
+          'version': 'OitcbHP6RwQc0JesmJsz-hQ2hPtMC84uSk3PXtWYq4EC',
         },
       ],
       'dep_type': 'cipd',
@@ -3719,7 +3719,7 @@
 
   'src/components/optimization_guide/internal': {
       'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' +
-        '946192c2badf817f08319c40ba15addf62565333',
+        'b969c7f54f353cf5679d9290f83a98f5ee609639',
       'condition': 'checkout_src_internal',
   },
 
@@ -3791,7 +3791,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        '923701b6eb8574642aa8d4c18b571e101fb265e5',
+        '69ec8e8ce45ad6fe43105363cddf5bec5829b322',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/agents/prompts/templates/cldescription.md b/agents/prompts/templates/cldescription.md
new file mode 100644
index 0000000..8790ab4
--- /dev/null
+++ b/agents/prompts/templates/cldescription.md
@@ -0,0 +1,73 @@
+# Instructions for Generating a Chromium Commit Message
+
+As an expert Chromium developer and Gerrit expert, your goal is to analyze the
+current session and generate a useful CL description. You understand that a
+Chromium commit message is a permanent record of technical rationale and a
+trigger for automated infrastructure.
+
+### 1. Pre-flight Investigation (Interactivity)
+
+Before generating the final draft, analyze the session history. If any of the
+following are missing or ambiguous, **STOP and ask the user for clarification**:
+
+- **The "Why":** If the technical rationale or motivation isn't explicitly clear
+  from the session history.
+- **Bug ID:** If no bug number was mentioned, ask if one should be associated.
+- **Internal vs. Public Bug:** If a bug ID is present, confirm if it's a public
+  Chromium bug or an internal Buganizer issue.
+- **Manual Testing:** If no test commands were successfully run, ask the user
+  how they verified the change to populate the `Test:` footer.
+
+### 2. Formatting Constraints (Mandatory)
+
+- **72-Column Wrap:** Every line (Subject and Body) **MUST** be hard-wrapped at
+  72 characters.
+- **Subject Line:** A single, concise summary. Prefix it with the relevant
+  component in brackets, e.g., `[Omnibox]: ...`. The entire subject line
+  **MUST** be under 50 characters if possible, and no more than 72 characters.
+- **Subject Spacing:** There **MUST** be exactly one blank line after the
+  subject.
+- **Footer Spacing:** There should be no blank lines within the footer block.
+- **No Markdown-style Hyperlinks:** DO NOT use the markdown-style hyperlinks
+  (e.g., `[link](url)`).
+
+### 3. Body Content Requirements
+
+- **Content over Code:** Do not just list what changed. Focus on **why** it was
+  necessary.
+- **Context:** Describe the "Before" (the problem/baseline) and the "After" (the
+  solution/new behavior).
+- **Documentation Links:** Do not include any links (e.g., to design docs or
+  other CLs) unless specifically requested. Use the format
+  `https://crrev.com/c/NUMBER` for Gerrit CL references.
+- **Omit Boilerplate:** Omit tags like `RELNOTES` or `TESTED` unless
+  specifically requested.
+
+### 4. Critical Footer Logic
+
+- **Internal Bugs (Buganizer):** MUST use the `b:` prefix. Example:
+  `Bug: b:123456`.
+  - **WARNING:** Never use the `b/123` format; it triggers OSS lint warnings.
+- **Public Bugs:** Use the bare number. Example: `Bug: 123456`.
+- **Bug: None:** IF NO BUG is associated with the session, **DO NOT** include a
+  `Bug:` line at all. Do not write `Bug: None`.
+- **Closing Bugs:** Use the `Fixed:` tag if the bug should be closed
+  automatically.
+- **Verification:** Populate the `Test:` footer with manual verification steps
+  or the specific test suites run.
+
+______________________________________________________________________
+
+## Final Message Template:
+
+```
+[Component]: [Short summary of change (< 50 chars)]
+
+[Description explaining the "Why" and "How". Focus on rationale,
+previous behavior, and the impact of the change. Wrap this
+block strictly at 72 characters. You can omit this body if the
+diff is short and self-explanatory.]
+
+Bug: [b:ID or ID]
+Test: [Manual test commands or verification steps]
+```
diff --git a/agents/prompts/templates/commit_message.md b/agents/prompts/templates/commit_message.md
deleted file mode 100644
index 6ff72d8..0000000
--- a/agents/prompts/templates/commit_message.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# Instructions for Generating a Chromium Commit Message
-
-As an expert Chromium developer and Gerrit specialist, your goal is to analyze the current session and generate a useful Change List (CL) description. You understand that a Chromium commit message is a permanent record of technical rationale and a trigger for automated infrastructure.
-
-### 1. Pre-flight Investigation (Interactivity)
-Before generating the final draft, analyze the session history. If any of the following are missing or ambiguous, **STOP and ask the user for clarification**:
-*   **The "Why":** If the technical rationale or motivation isn't explicitly clear from the session history.
-*   **Bug ID:** If no bug number was mentioned, ask if one should be associated.
-*   **Internal vs. Public Bug:** If a bug ID is present, confirm if it's a public Chromium bug or an internal Buganizer issue.
-*   **Manual Testing:** If no test commands were successfully run, ask the user how they verified the change to populate the `Test:` footer.
-
-### 2. Formatting Constraints (Mandatory)
-*   **72-Column Wrap:** Every line (Subject and Body) **MUST** be hard-wrapped at 72 characters.
-*   **Subject Line:** A single, concise summary. Prefix it with the relevant component in brackets, e.g., `[Omnibox]: ...`.
-*   **Subject Spacing:** There **MUST** be exactly one blank line after the subject.
-*   **Footer Spacing:** There should be no blank lines within the footer block.
-
-### 3. Body Content Requirements
-*   **Content over Code:** Do not just list what changed. Focus on **why** it was necessary.
-*   **Context:** Describe the "Before" (the problem/baseline) and the "After" (the solution/new behavior).
-*   **Reference Links:** Use the format `https://crrev.com/c/NUMBER` for Gerrit CL references.
-
-### 4. Critical Footer Logic
-*   **Internal Bugs (Buganizer):** MUST use the `b:` prefix. Example: `Bug: b:123456`.
-    *   **WARNING:** Never use the `b/123` format; it triggers OSS lint warnings.
-*   **Public Bugs:** Use the bare number. Example: `Bug: 123456`.
-*   **Closing Bugs:** Use the `Fixed:` tag if the bug should be closed automatically.
-*   **Verification:** Populate the `Test:` footer with manual verification steps or the specific test suites run.
-
----
-
-## Final Message Template:
-
-```
-[Component]: [Short summary of change]
-
-[Description explaining the "Why" and "How". Focus on rationale,
-previous behavior, and the impact of the change. Wrap this
-block strictly at 72 characters.]
-
-Bug: [b:ID or ID]
-Test: [Manual test commands or verification steps]
-```
diff --git a/agents/testing/gemini_provider.py b/agents/testing/gemini_provider.py
index 4ff0c49c..49a360e 100644
--- a/agents/testing/gemini_provider.py
+++ b/agents/testing/gemini_provider.py
@@ -35,6 +35,8 @@
 ]
 DEFAULT_SKILLS = []
 
+MODEL = 'gemini-3.1-pro-preview'
+
 
 @dataclasses.dataclass
 class GeminiCliArguments:
@@ -337,7 +339,7 @@
         command.append(node_bin)
     gemini_cli_bin = provider_vars.get('gemini_cli_bin',
                                        gemini_helpers.get_gemini_executable())
-    command.extend([gemini_cli_bin, '-y', '--model', 'gemini-2.5-pro'])
+    command.extend([gemini_cli_bin, '-y', '--model', MODEL])
 
     sandbox_flags = []
     if provider_vars.get('sandbox', False):
diff --git a/agents/testing/gemini_provider_unittest.py b/agents/testing/gemini_provider_unittest.py
index 61d24d6..2583e2d 100755
--- a/agents/testing/gemini_provider_unittest.py
+++ b/agents/testing/gemini_provider_unittest.py
@@ -292,7 +292,7 @@
 
         self.assertEqual(error, '')
         self.assertEqual(args.command,
-                         ['gemini', '-y', '--model', 'gemini-2.5-pro'])
+                         ['gemini', '-y', '--model', 'gemini-3.1-pro-preview'])
         self.assertIsNone(args.home_dir)
         self.assertEqual(args.timeout_seconds,
                          gemini_provider.DEFAULT_TIMEOUT_SECONDS)
@@ -312,8 +312,9 @@
             provider_vars, provider_config, user_prompt)
 
         self.assertEqual(error, '')
-        self.assertEqual(args.command,
-                         ['/custom/gemini', '-y', '--model', 'gemini-2.5-pro'])
+        self.assertEqual(
+            args.command,
+            ['/custom/gemini', '-y', '--model', 'gemini-3.1-pro-preview'])
 
     def test_sandbox_enabled(self):
         """Tests that sandbox flags are added when sandbox is enabled."""
@@ -328,7 +329,7 @@
         self.assertEqual(error, '')
         self.assertEqual(
             args.command,
-            ['gemini', '-y', '--model', 'gemini-2.5-pro', '--sandbox'])
+            ['gemini', '-y', '--model', 'gemini-3.1-pro-preview', '--sandbox'])
         self.assertIn('SANDBOX_FLAGS', args.env)
         self.assertEqual(args.env['SANDBOX_FLAGS'], '--sandbox-flag')
 
diff --git a/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt b/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt
index 0e9d2b2a..4262ffd 100644
--- a/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt
@@ -1363,14 +1363,20 @@
     getter nextElementSibling
     getter previousElementSibling
     method after
+    method afterHTML
+    method afterHTMLUnsafe
     method appendData
     method before
+    method beforeHTML
+    method beforeHTMLUnsafe
     method constructor
     method deleteData
     method insertData
     method remove
     method replaceData
     method replaceWith
+    method replaceWithHTML
+    method replaceWithHTMLUnsafe
     method substringData
     setter data
 interface Clipboard : EventTarget
@@ -2311,10 +2317,16 @@
     getter publicId
     getter systemId
     method after
+    method afterHTML
+    method afterHTMLUnsafe
     method before
+    method beforeHTML
+    method beforeHTMLUnsafe
     method constructor
     method remove
     method replaceWith
+    method replaceWithHTML
+    method replaceWithHTMLUnsafe
 interface DragEvent : MouseEvent
     attribute @@toStringTag
     getter dataTransfer
@@ -2356,7 +2368,6 @@
     attribute @@toStringTag
     attribute @@unscopables
     getter activeViewTransition
-    getter anchorElement
     getter ariaActiveDescendantElement
     getter ariaAtomic
     getter ariaAutoComplete
@@ -2457,11 +2468,17 @@
     getter slot
     getter tagName
     method after
+    method afterHTML
+    method afterHTMLUnsafe
     method animate
     method append
+    method appendHTML
+    method appendHTMLUnsafe
     method ariaNotify
     method attachShadow
     method before
+    method beforeHTML
+    method beforeHTMLUnsafe
     method checkVisibility
     method closest
     method computedStyleMap
@@ -2488,6 +2505,8 @@
     method matches
     method moveBefore
     method prepend
+    method prependHTML
+    method prependHTMLUnsafe
     method pseudo
     method querySelector
     method querySelectorAll
@@ -2498,6 +2517,8 @@
     method removeAttributeNode
     method replaceChildren
     method replaceWith
+    method replaceWithHTML
+    method replaceWithHTMLUnsafe
     method requestFullscreen
     method requestPointerLock
     method scroll
@@ -2513,13 +2534,14 @@
     method setHTMLUnsafe
     method setPointerCapture
     method startViewTransition
+    method streamAppendHTML
     method streamAppendHTMLUnsafe
+    method streamHTML
     method streamHTMLUnsafe
     method toggleAttribute
     method webkitMatchesSelector
     method webkitRequestFullScreen
     method webkitRequestFullscreen
-    setter anchorElement
     setter ariaActiveDescendantElement
     setter ariaAtomic
     setter ariaAutoComplete
@@ -9301,15 +9323,21 @@
     getter serializable
     getter slotAssignment
     getter styleSheets
+    method appendHTML
+    method appendHTMLUnsafe
     method constructor
     method elementFromPoint
     method elementsFromPoint
     method getAnimations
     method getHTML
     method getSelection
+    method prependHTML
+    method prependHTMLUnsafe
     method setHTML
     method setHTMLUnsafe
+    method streamAppendHTML
     method streamAppendHTMLUnsafe
+    method streamHTML
     method streamHTMLUnsafe
     setter adoptedStyleSheets
     setter fullscreenElement
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index ae8abcdf..38d6125 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -1093,11 +1093,6 @@
 BASE_FEATURE(kInstantTethering, base::FEATURE_ENABLED_BY_DEFAULT);
 
 // Enables or disables the internal server side speech recognition on ChromeOS.
-// Controls the launched locales.
-BASE_FEATURE(kInternalServerSideSpeechRecognition,
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
-// Enables or disables the internal server side speech recognition on ChromeOS.
 // The supported locales for this feature are specified using the locales
 // filter in finch config.
 BASE_FEATURE(kInternalServerSideSpeechRecognitionByFinch,
@@ -2712,9 +2707,7 @@
 
 bool IsInternalServerSideSpeechRecognitionEnabled() {
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-
-  return (ShouldForceEnableServerSideSpeechRecognition() ||
-          base::FeatureList::IsEnabled(kInternalServerSideSpeechRecognition));
+  return true;
 #else
   return false;
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index 3ee182f4..98d706e 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -512,8 +512,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kInstantTethering);
 // TODO(b/288273641): Clean up the server speech recognition related flags.
 COMPONENT_EXPORT(ASH_CONSTANTS)
-BASE_DECLARE_FEATURE(kInternalServerSideSpeechRecognition);
-COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kInternalServerSideSpeechRecognitionByFinch);
 COMPONENT_EXPORT(ASH_CONSTANTS)
 BASE_DECLARE_FEATURE(kInternalServerSideSpeechRecognitionUSMModelFinch);
diff --git a/ash/wm/resize_shadow.cc b/ash/wm/resize_shadow.cc
index 80b5730f..49a460f 100644
--- a/ash/wm/resize_shadow.cc
+++ b/ash/wm/resize_shadow.cc
@@ -172,13 +172,13 @@
 void ResizeShadow::OnColorProviderChanged() {
   // This function will also be called when the color provider source is
   // destroyed. We should guarantee the color provider exists.
-  if (params_.color.IsSemantic() && GetColorProviderSource()) {
+  if (params_.color.IsLogical() && GetColorProviderSource()) {
     UpdateShadowLayer();
   }
 }
 
 void ResizeShadow::OnWindowParentToRootWindow() {
-  if (params_.color.IsSemantic()) {
+  if (params_.color.IsLogical()) {
     Observe(RootWindowController::ForWindow(window_)->color_provider_source());
   }
 }
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 37d9804..01a5427 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -5517,6 +5517,7 @@
     sources = [
       "android/java/src/org/chromium/base/AconfigFlaggedApiDelegate.java",
       "android/java/src/org/chromium/base/BindingRequestQueue.java",
+      "android/java/src/org/chromium/base/PasswordEchoSplitSettingDelegate.java",
       "android/java/src/org/chromium/base/SelectionActionMenuClientWrapper.java",
       "android/java/src/org/chromium/base/serial/SerialManager.java",
       "android/java/src/org/chromium/base/serial/SerialPort.java",
diff --git a/base/android/callback_android.h b/base/android/callback_android.h
index e81f0815..01433b54 100644
--- a/base/android/callback_android.h
+++ b/base/android/callback_android.h
@@ -7,6 +7,7 @@
 
 #include <string>
 #include <type_traits>
+#include <utility>
 #include <vector>
 
 #include "base/android/scoped_java_ref.h"
@@ -98,11 +99,10 @@
                [](base::OnceCallback<R(Arg1, Arg2)> captured_callback,
                   const jni_zero::JavaRef<jobject>& j_result1,
                   const jni_zero::JavaRef<jobject>& j_result2) {
+                 JNIEnv* env = jni_zero::AttachCurrentThread();
                  std::move(captured_callback)
-                     .Run(jni_zero::FromJniType<std::decay_t<Arg1>>(
-                              jni_zero::AttachCurrentThread(), j_result1),
-                          jni_zero::FromJniType<std::decay_t<Arg2>>(
-                              jni_zero::AttachCurrentThread(), j_result2));
+                     .Run(jni_zero::FromJniType<Arg1>(env, j_result1),
+                          jni_zero::FromJniType<Arg2>(env, j_result2));
                },
                std::move(callback)));
 }
@@ -119,11 +119,9 @@
           [](const base::RepeatingCallback<R(Arg1, Arg2)>& captured_callback,
              const jni_zero::JavaRef<jobject>& j_result1,
              const jni_zero::JavaRef<jobject>& j_result2) {
-            captured_callback.Run(
-                jni_zero::FromJniType<std::decay_t<Arg1>>(
-                    jni_zero::AttachCurrentThread(), j_result1),
-                jni_zero::FromJniType<std::decay_t<Arg2>>(
-                    jni_zero::AttachCurrentThread(), j_result2));
+            JNIEnv* env = jni_zero::AttachCurrentThread();
+            captured_callback.Run(jni_zero::FromJniType<Arg1>(env, j_result1),
+                                  jni_zero::FromJniType<Arg2>(env, j_result2));
           },
           callback));
 }
@@ -138,9 +136,9 @@
       env, base::BindOnce(
                [](base::OnceCallback<R(Arg)> captured_callback,
                   const jni_zero::JavaRef<jobject>& j_result) {
-                 auto result = jni_zero::FromJniType<std::decay_t<Arg>>(
-                     jni_zero::AttachCurrentThread(), j_result);
-                 std::move(captured_callback).Run(std::move(result));
+                 JNIEnv* env = jni_zero::AttachCurrentThread();
+                 std::move(captured_callback)
+                     .Run(jni_zero::FromJniType<Arg>(env, j_result));
                },
                std::move(callback)));
 }
@@ -166,14 +164,14 @@
     JNIEnv* env,
     const base::RepeatingCallback<R(Arg)>& callback) {
   return ToJniCallback(
-      env, base::BindRepeating(
-               [](const base::RepeatingCallback<R(Arg)>& captured_callback,
-                  const jni_zero::JavaRef<jobject>& j_result) {
-                 Arg result = jni_zero::FromJniType<Arg>(
-                     jni_zero::AttachCurrentThread(), j_result);
-                 captured_callback.Run(std::move(result));
-               },
-               callback));
+      env,
+      base::BindRepeating(
+          [](const base::RepeatingCallback<R(Arg)>& captured_callback,
+             const jni_zero::JavaRef<jobject>& j_result) {
+            JNIEnv* env = jni_zero::AttachCurrentThread();
+            captured_callback.Run(jni_zero::FromJniType<Arg>(env, j_result));
+          },
+          callback));
 }
 
 // Java Callbacks don't return a value so any return value by the passed in
@@ -232,45 +230,19 @@
 template <typename T>
 void RunJavaCallback(const jni_zero::ScopedJavaGlobalRef<jobject>& callback,
                      T arg) {
-  if constexpr (requires { jni_zero::ToJniType(nullptr, std::move(arg)); }) {
-    JNIEnv* env = jni_zero::AttachCurrentThread();
-    base::android::RunObjectCallbackAndroid(
-        callback, jni_zero::ToJniType(env, std::move(arg)));
-  } else {
-    static_assert(
-        sizeof(T) == 0,
-        "Could not find ToJniType<> specialization for the callback's "
-        "parameter. Make sure the header declaring it is #included before "
-        "base/callback_android.h");
-  }
+  JNIEnv* env = jni_zero::AttachCurrentThread();
+  base::android::RunObjectCallbackAndroid(
+      callback, jni_zero::ToJniType(env, std::move(arg)));
 }
 
 template <typename T1, typename T2>
 void RunJavaCallback2(const jni_zero::ScopedJavaGlobalRef<jobject>& callback,
                       T1 arg1,
                       T2 arg2) {
-  if constexpr (requires { jni_zero::ToJniType(nullptr, std::move(arg1)); }) {
-    if constexpr (requires { jni_zero::ToJniType(nullptr, std::move(arg2)); }) {
-      JNIEnv* env = jni_zero::AttachCurrentThread();
-      base::android::RunObjectCallbackAndroid2(
-          callback, jni_zero::ToJniType(env, std::move(arg1)),
-          jni_zero::ToJniType(env, std::move(arg2)));
-    } else {
-      static_assert(
-          sizeof(T1) == 0,
-          "Could not find ToJniType<> specialization for the callback's "
-          "second parameter. Make sure the header declaring it is #included "
-          "before "
-          "base/callback_android.h");
-    }
-  } else {
-    static_assert(
-        sizeof(T1) == 0,
-        "Could not find ToJniType<> specialization for the callback's "
-        "first parameter. Make sure the header declaring it is #included "
-        "before "
-        "base/callback_android.h");
-  }
+  JNIEnv* env = jni_zero::AttachCurrentThread();
+  base::android::RunObjectCallbackAndroid2(
+      callback, jni_zero::ToJniType(env, std::move(arg1)),
+      jni_zero::ToJniType(env, std::move(arg2)));
 }
 
 }  // namespace base::android::internal
@@ -333,6 +305,7 @@
                     std::remove_cvref_t<T>>::value) {
     return base::android::ToJniCallback(env, std::move(callback));
   } else {
+    // Repeating callback.
     return base::android::ToJniCallback(env, std::forward<T>(callback));
   }
 }
diff --git a/base/android/java/src/org/chromium/base/AconfigFlaggedApiDelegate.java b/base/android/java/src/org/chromium/base/AconfigFlaggedApiDelegate.java
index 06af37e..34edfcf5 100644
--- a/base/android/java/src/org/chromium/base/AconfigFlaggedApiDelegate.java
+++ b/base/android/java/src/org/chromium/base/AconfigFlaggedApiDelegate.java
@@ -366,6 +366,14 @@
     }
 
     /**
+     * Returns the {@link PasswordEchoSplitSettingDelegate} if the feature to split the Android
+     * setting 'Show passwords' is enabled. the feature is enabled. Returns null otherwise.
+     */
+    default @Nullable PasswordEchoSplitSettingDelegate getPasswordEchoSplitSettingDelegate() {
+        return null;
+    }
+
+    /**
      * Constructs {@link WebAppQueryRequest} and calls {@link
      * android.content.pm.webapp.WebAppManager#query(@NonNull WebAppQueryRequest
      * request, @NonNull @CallbackExecutor Executor executor, @NonNull IntConsumer callback)} with
diff --git a/base/android/java/src/org/chromium/base/PasswordEchoSplitSettingDelegate.java b/base/android/java/src/org/chromium/base/PasswordEchoSplitSettingDelegate.java
new file mode 100644
index 0000000..1fd4bd155
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/PasswordEchoSplitSettingDelegate.java
@@ -0,0 +1,20 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import org.chromium.build.annotations.NullMarked;
+
+/** Delegate interface for Password Echo Split settings. */
+@NullMarked
+public interface PasswordEchoSplitSettingDelegate {
+    /** Registers a callback to be invoked when the password echo settings change. */
+    void registerCallback(Runnable callback);
+
+    /** Returns whether the physical keyboard password echo setting is enabled. */
+    boolean isPhysicalSettingEnabled();
+
+    /** Returns whether the touch keyboard password echo setting is enabled. */
+    boolean isTouchSettingEnabled();
+}
diff --git a/base/android/jni_callbacks_test_support.cc b/base/android/jni_callbacks_test_support.cc
index e3ec79c3..4d306f72 100644
--- a/base/android/jni_callbacks_test_support.cc
+++ b/base/android/jni_callbacks_test_support.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <jni.h>
-
 #include "base/android/callback_android.h"
+#include "base/android/jni_string.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
+#include "base/no_destructor.h"
 
 // Must come after all headers that specialize FromJniType() / ToJniType().
 #include "base/base_junit_tests_jni/JniCallbacksTest_jni.h"
@@ -21,110 +21,171 @@
 bool g_once_callback2_result1 = false;
 int g_once_callback2_result2 = 0;
 int g_repeating_callback2_result_count = 0;
+int g_repeating_callback_with_subtype_run_count = 0;
+
+std::string& GetOnceCallbackWithSubtypeResult() {
+  static base::NoDestructor<std::string> instance;
+  return *instance;
+}
 }  // namespace
 
 static void JNI_JniCallbacksTest_ResetCounters(JNIEnv* env) {
   g_once_closure_run_count = 0;
   g_once_callback_result = false;
-  g_repeating_closure_run_count = 0;
-  g_repeating_callback_result_count = 0;
   g_once_callback2_result1 = false;
   g_once_callback2_result2 = 0;
+  g_repeating_closure_run_count = 0;
+  g_repeating_callback_result_count = 0;
   g_repeating_callback2_result_count = 0;
+  GetOnceCallbackWithSubtypeResult().clear();
+  g_repeating_callback_with_subtype_run_count = 0;
 }
 
-static base::OnceClosure JNI_JniCallbacksTest_GetOnceClosure() {
+static base::OnceClosure JNI_JniCallbacksTest_GetOnceClosure(JNIEnv* env) {
   return base::BindOnce([]() { g_once_closure_run_count++; });
 }
 
-static jint JNI_JniCallbacksTest_GetOnceClosureRunCount() {
+static jint JNI_JniCallbacksTest_GetOnceClosureRunCount(JNIEnv* env) {
   return g_once_closure_run_count;
 }
 
-static base::OnceCallback<void(bool)> JNI_JniCallbacksTest_GetOnceCallback() {
+static base::OnceCallback<void(bool)> JNI_JniCallbacksTest_GetOnceCallback(
+    JNIEnv* env) {
   return base::BindOnce([](bool r) { g_once_callback_result = r; });
 }
 
-static jboolean JNI_JniCallbacksTest_GetOnceCallbackResult() {
+static jboolean JNI_JniCallbacksTest_GetOnceCallbackResult(JNIEnv* env) {
   return g_once_callback_result;
 }
 
-static base::RepeatingClosure JNI_JniCallbacksTest_GetRepeatingClosure() {
+static base::RepeatingClosure JNI_JniCallbacksTest_GetRepeatingClosure(
+    JNIEnv* env) {
   return base::BindRepeating([]() { g_repeating_closure_run_count++; });
 }
 
-static jint JNI_JniCallbacksTest_GetRepeatingClosureRunCount() {
+static jint JNI_JniCallbacksTest_GetRepeatingClosureRunCount(JNIEnv* env) {
   return g_repeating_closure_run_count;
 }
 
 static base::RepeatingCallback<void(bool)>
-JNI_JniCallbacksTest_GetRepeatingCallback() {
+JNI_JniCallbacksTest_GetRepeatingCallback(JNIEnv* env) {
   return base::BindRepeating(
       [](bool r) { g_repeating_callback_result_count++; });
 }
 
-static jint JNI_JniCallbacksTest_GetRepeatingCallbackResultCount() {
+static jint JNI_JniCallbacksTest_GetRepeatingCallbackResultCount(JNIEnv* env) {
   return g_repeating_callback_result_count;
 }
 
-static base::OnceCallback<void(bool, int32_t)>
-JNI_JniCallbacksTest_GetOnceCallback2() {
-  return base::BindOnce([](bool r1, int32_t r2) {
+static base::OnceCallback<void(bool, const jni_zero::JavaRef<jobject>&)>
+JNI_JniCallbacksTest_GetOnceCallback2(JNIEnv* env) {
+  return base::BindOnce([](bool r1, const jni_zero::JavaRef<jobject>& r2) {
     g_once_callback2_result1 = r1;
-    g_once_callback2_result2 = r2;
+    g_once_callback2_result2 =
+        jni_zero::FromJniType<int32_t>(jni_zero::AttachCurrentThread(), r2);
   });
 }
 
-static jboolean JNI_JniCallbacksTest_GetOnceCallback2Result1() {
+static jboolean JNI_JniCallbacksTest_GetOnceCallback2Result1(JNIEnv* env) {
   return g_once_callback2_result1;
 }
 
-static jint JNI_JniCallbacksTest_GetOnceCallback2Result2() {
+static jint JNI_JniCallbacksTest_GetOnceCallback2Result2(JNIEnv* env) {
   return g_once_callback2_result2;
 }
 
 static base::RepeatingCallback<void(bool, int32_t)>
-JNI_JniCallbacksTest_GetRepeatingCallback2() {
+JNI_JniCallbacksTest_GetRepeatingCallback2(JNIEnv* env) {
   return base::BindRepeating(
       [](bool r1, int32_t r2) { g_repeating_callback2_result_count++; });
 }
 
-static jint JNI_JniCallbacksTest_GetRepeatingCallback2ResultCount() {
+static jint JNI_JniCallbacksTest_GetRepeatingCallback2ResultCount(JNIEnv* env) {
   return g_repeating_callback2_result_count;
 }
 
-static void JNI_JniCallbacksTest_PassOnceClosure(base::OnceClosure closure) {
+static base::OnceCallback<void(const jni_zero::JavaRef<jstring>&)>
+JNI_JniCallbacksTest_GetOnceCallbackWithSubtype(JNIEnv* env) {
+  return base::BindOnce([](const jni_zero::JavaRef<jstring>& r) {
+    GetOnceCallbackWithSubtypeResult() =
+        ConvertJavaStringToUTF8(jni_zero::AttachCurrentThread(), r);
+  });
+}
+
+static ScopedJavaLocalRef<jstring>
+JNI_JniCallbacksTest_GetOnceCallbackWithSubtypeResult(JNIEnv* env) {
+  return ConvertUTF8ToJavaString(env, GetOnceCallbackWithSubtypeResult());
+}
+
+static base::RepeatingCallback<void(const jni_zero::JavaRef<jstring>&)>
+JNI_JniCallbacksTest_GetRepeatingCallbackWithSubtype(JNIEnv* env) {
+  return base::BindRepeating([](const jni_zero::JavaRef<jstring>& r) {
+    g_repeating_callback_with_subtype_run_count++;
+  });
+}
+
+static jint JNI_JniCallbacksTest_GetRepeatingCallbackWithSubtypeRunCount(
+    JNIEnv* env) {
+  return g_repeating_callback_with_subtype_run_count;
+}
+
+static void JNI_JniCallbacksTest_PassOnceClosure(JNIEnv* env,
+                                                 base::OnceClosure closure) {
   std::move(closure).Run();
 }
 
 static void JNI_JniCallbacksTest_PassOnceCallback(
+    JNIEnv* env,
     base::OnceCallback<void(int32_t)> callback) {
   std::move(callback).Run(42);
 }
 
 static void JNI_JniCallbacksTest_PassRepeatingClosure(
+    JNIEnv* env,
     base::RepeatingClosure closure) {
   closure.Run();
   closure.Run();
 }
 
 static void JNI_JniCallbacksTest_PassRepeatingCallback(
+    JNIEnv* env,
     base::RepeatingCallback<void(int32_t)> callback) {
   callback.Run(1);
   callback.Run(2);
 }
 
 static void JNI_JniCallbacksTest_PassOnceCallback2(
+    JNIEnv* env,
     base::OnceCallback<void(bool, int32_t)> callback) {
   std::move(callback).Run(true, 100);
 }
 
 static void JNI_JniCallbacksTest_PassRepeatingCallback2(
+    JNIEnv* env,
     base::RepeatingCallback<void(bool, int32_t)> callback) {
   callback.Run(true, 1);
   callback.Run(false, 2);
 }
 
+static void JNI_JniCallbacksTest_PassOnceCallbackWithSubtype(
+    JNIEnv* env,
+    base::OnceCallback<void(const jni_zero::JavaRef<jstring>&)> callback) {
+  std::move(callback).Run(ConvertUTF8ToJavaString(env, "test string"));
+}
+
+static void JNI_JniCallbacksTest_PassOnceCallbackWithScopedSubtype(
+    JNIEnv* env,
+    base::OnceCallback<void(jni_zero::ScopedJavaLocalRef<jstring>)> callback) {
+  std::move(callback).Run(ConvertUTF8ToJavaString(env, "scoped string"));
+}
+
+static void JNI_JniCallbacksTest_PassRepeatingCallbackWithSubtype(
+    JNIEnv* env,
+    base::RepeatingCallback<void(const jni_zero::JavaRef<jstring>&)> callback) {
+  callback.Run(ConvertUTF8ToJavaString(env, "s1"));
+  callback.Run(ConvertUTF8ToJavaString(env, "s2"));
+}
+
 }  // namespace base::android
 
 DEFINE_JNI(JniCallbacksTest)
diff --git a/base/android/junit/src/org/chromium/base/JniCallbacksTest.java b/base/android/junit/src/org/chromium/base/JniCallbacksTest.java
index 95b55ec..94c7cec9 100644
--- a/base/android/junit/src/org/chromium/base/JniCallbacksTest.java
+++ b/base/android/junit/src/org/chromium/base/JniCallbacksTest.java
@@ -123,6 +123,61 @@
         Assert.assertEquals(2, resultCount[0]);
     }
 
+    @Test
+    public void testJavaToOnceCallbackWithSubtype() {
+        String[] result = {null};
+        JniCallbacksTestJni.get().passOnceCallbackWithSubtype(r -> result[0] = r);
+        Assert.assertEquals("test string", result[0]);
+    }
+
+    @Test
+    public void testJavaToOnceCallbackWithScopedSubtype() {
+        String[] result = {null};
+        JniCallbacksTestJni.get().passOnceCallbackWithScopedSubtype(r -> result[0] = r);
+        Assert.assertEquals("scoped string", result[0]);
+    }
+
+    @Test
+    public void testJavaToRepeatingCallbackWithSubtype() {
+        String[] results = new String[2];
+        int[] resultCount = {0};
+        JniCallbacksTestJni.get()
+                .passRepeatingCallbackWithSubtype(
+                        r -> {
+                            results[resultCount[0]] = r;
+                            resultCount[0]++;
+                        });
+        Assert.assertEquals(2, resultCount[0]);
+        Assert.assertEquals("s1", results[0]);
+        Assert.assertEquals("s2", results[1]);
+    }
+
+    @Test
+    public void testNativeToOnceCallbackWithSubtype() {
+        Callback<String> c = JniCallbacksTestJni.get().getOnceCallbackWithSubtype();
+        c.onResult("native subtype");
+        Assert.assertEquals(
+                "native subtype", JniCallbacksTestJni.get().getOnceCallbackWithSubtypeResult());
+    }
+
+    @Test
+    public void testNativeToRepeatingCallbackWithSubtype() {
+        JniRepeatingCallback<String> c =
+                JniCallbacksTestJni.get().getRepeatingCallbackWithSubtype();
+        c.onResult("s1");
+        c.onResult("s2");
+        Assert.assertEquals(2, JniCallbacksTestJni.get().getRepeatingCallbackWithSubtypeRunCount());
+        c.destroy();
+    }
+
+    @Test
+    public void testPassReturnedOnceCallbackWithSubtype() {
+        Callback<String> c = JniCallbacksTestJni.get().getOnceCallbackWithSubtype();
+        JniCallbacksTestJni.get().passOnceCallbackWithSubtype(c);
+        Assert.assertEquals(
+                "test string", JniCallbacksTestJni.get().getOnceCallbackWithSubtypeResult());
+    }
+
     @NativeMethods
     interface Natives {
         void resetCounters();
@@ -147,7 +202,7 @@
 
         int getRepeatingCallbackResultCount();
 
-        @JniType("base::OnceCallback<void(bool, int32_t)>")
+        @JniType("base::OnceCallback<void(bool, jni_zero::JavaRef<jobject>)>")
         Callback2<Boolean, Integer> getOnceCallback2();
 
         boolean getOnceCallback2Result1();
@@ -159,6 +214,16 @@
 
         int getRepeatingCallback2ResultCount();
 
+        @JniType("base::OnceCallback<void(const jni_zero::JavaRef<jstring>&)>")
+        Callback<String> getOnceCallbackWithSubtype();
+
+        String getOnceCallbackWithSubtypeResult();
+
+        @JniType("base::RepeatingCallback<void(const jni_zero::JavaRef<jstring>&)>")
+        JniRepeatingCallback<String> getRepeatingCallbackWithSubtype();
+
+        int getRepeatingCallbackWithSubtypeRunCount();
+
         void passOnceClosure(@JniType("base::OnceClosure") Runnable r);
 
         void passOnceCallback(@JniType("base::OnceCallback<void(int32_t)>") Callback<Integer> c);
@@ -174,5 +239,17 @@
         void passRepeatingCallback2(
                 @JniType("base::RepeatingCallback<void(bool, int32_t)>")
                         Callback2<Boolean, Integer> c);
+
+        void passOnceCallbackWithSubtype(
+                @JniType("base::OnceCallback<void(const jni_zero::JavaRef<jstring>&)>")
+                        Callback<String> c);
+
+        void passOnceCallbackWithScopedSubtype(
+                @JniType("base::OnceCallback<void(jni_zero::ScopedJavaLocalRef<jstring>)>")
+                        Callback<String> c);
+
+        void passRepeatingCallbackWithSubtype(
+                @JniType("base::RepeatingCallback<void(const jni_zero::JavaRef<jstring>&)>")
+                        Callback<String> c);
     }
 }
diff --git a/base/memory_coordinator/async_memory_consumer_registration.cc b/base/memory_coordinator/async_memory_consumer_registration.cc
index 6c547cc..013d841d 100644
--- a/base/memory_coordinator/async_memory_consumer_registration.cc
+++ b/base/memory_coordinator/async_memory_consumer_registration.cc
@@ -24,7 +24,7 @@
   MainThread() { DETACH_FROM_THREAD(thread_checker_); }
 
   void Init(std::string consumer_id,
-            MemoryConsumerTraits traits,
+            std::optional<MemoryConsumerTraits> traits,
             CheckUnregister check_unregister,
             CheckRegistryExists check_registry_exists,
             WeakPtr<AsyncMemoryConsumerRegistration> parent,
@@ -72,7 +72,7 @@
 
 AsyncMemoryConsumerRegistration::AsyncMemoryConsumerRegistration(
     std::string_view consumer_id,
-    MemoryConsumerTraits traits,
+    std::optional<MemoryConsumerTraits> traits,
     MemoryConsumer* consumer,
     CheckUnregister check_unregister,
     CheckRegistryExists check_registry_exists)
diff --git a/base/memory_coordinator/async_memory_consumer_registration.h b/base/memory_coordinator/async_memory_consumer_registration.h
index 80030df..cb58268 100644
--- a/base/memory_coordinator/async_memory_consumer_registration.h
+++ b/base/memory_coordinator/async_memory_consumer_registration.h
@@ -6,6 +6,7 @@
 #define BASE_MEMORY_COORDINATOR_ASYNC_MEMORY_CONSUMER_REGISTRATION_H_
 
 #include <memory>
+#include <optional>
 #include <string_view>
 
 #include "base/base_export.h"
@@ -28,7 +29,7 @@
 
   AsyncMemoryConsumerRegistration(
       std::string_view consumer_id,
-      MemoryConsumerTraits traits,
+      std::optional<MemoryConsumerTraits> traits,
       MemoryConsumer* consumer,
       CheckUnregister check_unregister = CheckUnregister::kEnabled,
       CheckRegistryExists check_registry_exists =
diff --git a/base/memory_coordinator/async_memory_consumer_registration_unittest.cc b/base/memory_coordinator/async_memory_consumer_registration_unittest.cc
index d3b5487..6c1a3c75 100644
--- a/base/memory_coordinator/async_memory_consumer_registration_unittest.cc
+++ b/base/memory_coordinator/async_memory_consumer_registration_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "base/memory_coordinator/async_memory_consumer_registration.h"
 
+#include <optional>
 #include <string_view>
 #include <utility>
 
@@ -26,7 +27,7 @@
 class TestAsyncMemoryConsumer : public MemoryConsumer {
  public:
   explicit TestAsyncMemoryConsumer(std::string_view consumer_id,
-                                   MemoryConsumerTraits traits)
+                                   std::optional<MemoryConsumerTraits> traits)
       : async_memory_consumer_registration_(consumer_id, traits, this) {}
 
   MOCK_METHOD(void, OnUpdateMemoryLimit, (), (override));
@@ -55,7 +56,7 @@
   auto async_task_runner = ThreadPool::CreateSequencedTaskRunner({});
 
   SequenceBound<TestAsyncMemoryConsumer> consumer(async_task_runner, "consumer",
-                                                  MemoryConsumerTraits{});
+                                                  std::nullopt);
 
   ASSERT_TRUE(test::RunUntil([&]() { return registry.size() == 1u; }));
 
diff --git a/base/memory_coordinator/memory_consumer.cc b/base/memory_coordinator/memory_consumer.cc
index a9b5c9d..9809a191 100644
--- a/base/memory_coordinator/memory_consumer.cc
+++ b/base/memory_coordinator/memory_consumer.cc
@@ -32,7 +32,7 @@
 
 MemoryConsumerRegistration::MemoryConsumerRegistration(
     std::string_view consumer_id,
-    MemoryConsumerTraits traits,
+    std::optional<MemoryConsumerTraits> traits,
     MemoryConsumer* consumer,
     CheckUnregister check_unregister,
     CheckRegistryExists check_registry_exists)
diff --git a/base/memory_coordinator/memory_consumer.h b/base/memory_coordinator/memory_consumer.h
index 0998e16..49b5f1f 100644
--- a/base/memory_coordinator/memory_consumer.h
+++ b/base/memory_coordinator/memory_consumer.h
@@ -5,6 +5,7 @@
 #ifndef BASE_MEMORY_COORDINATOR_MEMORY_CONSUMER_H_
 #define BASE_MEMORY_COORDINATOR_MEMORY_CONSUMER_H_
 
+#include <optional>
 #include <string>
 #include <string_view>
 
@@ -135,9 +136,12 @@
     kDisabled,
   };
 
+  // `traits` is only optional temporarily to assist with the migration of
+  // clients from MemoryPressureListener to MemoryCoordinator. It will be made
+  // mandatory in the future.
   MemoryConsumerRegistration(
       std::string_view consumer_id,
-      MemoryConsumerTraits traits,
+      std::optional<MemoryConsumerTraits> traits,
       MemoryConsumer* consumer,
       CheckUnregister check_unregister = CheckUnregister::kEnabled,
       CheckRegistryExists check_registry_exists =
diff --git a/base/memory_coordinator/memory_consumer_registry.cc b/base/memory_coordinator/memory_consumer_registry.cc
index 9caedac..a63fb94d 100644
--- a/base/memory_coordinator/memory_consumer_registry.cc
+++ b/base/memory_coordinator/memory_consumer_registry.cc
@@ -61,9 +61,10 @@
   CHECK(destruction_observers_.empty());
 }
 
-void MemoryConsumerRegistry::AddMemoryConsumer(std::string_view consumer_id,
-                                               MemoryConsumerTraits traits,
-                                               MemoryConsumer* consumer) {
+void MemoryConsumerRegistry::AddMemoryConsumer(
+    std::string_view consumer_id,
+    std::optional<MemoryConsumerTraits> traits,
+    MemoryConsumer* consumer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   OnMemoryConsumerAdded(consumer_id, traits,
                         RegisteredMemoryConsumer(consumer));
diff --git a/base/memory_coordinator/memory_consumer_registry.h b/base/memory_coordinator/memory_consumer_registry.h
index 7dd8e5c..e18edfd 100644
--- a/base/memory_coordinator/memory_consumer_registry.h
+++ b/base/memory_coordinator/memory_consumer_registry.h
@@ -5,6 +5,7 @@
 #ifndef BASE_MEMORY_COORDINATOR_MEMORY_CONSUMER_REGISTRY_H_
 #define BASE_MEMORY_COORDINATOR_MEMORY_CONSUMER_REGISTRY_H_
 
+#include <optional>
 #include <string_view>
 #include <utility>
 
@@ -54,7 +55,7 @@
   // Adds/Removes an instance of MemoryConsumer with a specific
   // `consumer_id` and `traits`.
   void AddMemoryConsumer(std::string_view consumer_id,
-                         MemoryConsumerTraits traits,
+                         std::optional<MemoryConsumerTraits> traits,
                          MemoryConsumer* consumer);
   void RemoveMemoryConsumer(std::string_view consumer_id,
                             MemoryConsumer* consumer);
@@ -78,7 +79,7 @@
 
  private:
   virtual void OnMemoryConsumerAdded(std::string_view consumer_id,
-                                     MemoryConsumerTraits traits,
+                                     std::optional<MemoryConsumerTraits> traits,
                                      RegisteredMemoryConsumer consumer) = 0;
   virtual void OnMemoryConsumerRemoved(std::string_view consumer_id,
                                        RegisteredMemoryConsumer consumer) = 0;
diff --git a/base/memory_coordinator/memory_consumer_registry_unittest.cc b/base/memory_coordinator/memory_consumer_registry_unittest.cc
index 708745bc..20922a1 100644
--- a/base/memory_coordinator/memory_consumer_registry_unittest.cc
+++ b/base/memory_coordinator/memory_consumer_registry_unittest.cc
@@ -26,7 +26,7 @@
   MOCK_METHOD(void,
               OnMemoryConsumerAdded,
               (std::string_view observer_id,
-               MemoryConsumerTraits traits,
+               std::optional<MemoryConsumerTraits> traits,
                RegisteredMemoryConsumer consumer),
               (override));
   MOCK_METHOD(void,
@@ -45,7 +45,7 @@
   const char kObserverId[] = "observer";
 
   EXPECT_CALL(registry, OnMemoryConsumerAdded(kObserverId, _, _));
-  registry.AddMemoryConsumer(kObserverId, {}, &consumer);
+  registry.AddMemoryConsumer(kObserverId, std::nullopt, &consumer);
 
   EXPECT_CALL(registry, OnMemoryConsumerRemoved(kObserverId, _));
   registry.RemoveMemoryConsumer(kObserverId, &consumer);
@@ -61,8 +61,7 @@
   const char kObserverId[] = "observer";
 
   EXPECT_CALL(registry.Get(), OnMemoryConsumerAdded(kObserverId, _, _));
-  registration.emplace(std::string_view(kObserverId), MemoryConsumerTraits{},
-                       &consumer);
+  registration.emplace(std::string_view(kObserverId), std::nullopt, &consumer);
 
   EXPECT_CALL(registry.Get(), OnMemoryConsumerRemoved(kObserverId, _));
   registration.reset();
@@ -80,8 +79,7 @@
   const char kObserverId[] = "observer";
 
   EXPECT_CALL(registry->Get(), OnMemoryConsumerAdded(kObserverId, _, _));
-  registration.emplace(std::string_view(kObserverId), MemoryConsumerTraits{},
-                       &consumer);
+  registration.emplace(std::string_view(kObserverId), std::nullopt, &consumer);
 
   EXPECT_CHECK_DEATH(registry.reset());
 
@@ -99,8 +97,7 @@
   std::optional<MemoryConsumerRegistration> registration;
 
   EXPECT_CALL(registry->Get(), OnMemoryConsumerAdded(kObserverId, _, _));
-  registration.emplace(std::string_view(kObserverId), MemoryConsumerTraits{},
-                       &consumer,
+  registration.emplace(std::string_view(kObserverId), std::nullopt, &consumer,
                        MemoryConsumerRegistration::CheckUnregister::kDisabled);
 
   EXPECT_CALL(registry->Get(), OnMemoryConsumerRemoved(kObserverId, _));
diff --git a/base/memory_coordinator/test_memory_consumer_registry.cc b/base/memory_coordinator/test_memory_consumer_registry.cc
index c9f6284..c9bfd3a 100644
--- a/base/memory_coordinator/test_memory_consumer_registry.cc
+++ b/base/memory_coordinator/test_memory_consumer_registry.cc
@@ -26,7 +26,7 @@
 
 void TestMemoryConsumerRegistry::OnMemoryConsumerAdded(
     std::string_view consumer_id,
-    MemoryConsumerTraits traits,
+    std::optional<MemoryConsumerTraits> traits,
     RegisteredMemoryConsumer consumer) {
   CHECK(!std::ranges::contains(memory_consumers_, consumer));
   memory_consumers_.push_back(consumer);
diff --git a/base/memory_coordinator/test_memory_consumer_registry.h b/base/memory_coordinator/test_memory_consumer_registry.h
index 7631e560..257de8d 100644
--- a/base/memory_coordinator/test_memory_consumer_registry.h
+++ b/base/memory_coordinator/test_memory_consumer_registry.h
@@ -24,7 +24,7 @@
 
   // MemoryConsumerRegistry:
   void OnMemoryConsumerAdded(std::string_view consumer_id,
-                             MemoryConsumerTraits traits,
+                             std::optional<MemoryConsumerTraits> traits,
                              RegisteredMemoryConsumer consumer) override;
   void OnMemoryConsumerRemoved(std::string_view consumer_id,
                                RegisteredMemoryConsumer consumer) override;
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 5af3165..efc5f1e 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -2294,10 +2294,6 @@
       # should always be added for clang builds.
       cflags += [ "-Wexit-time-destructors" ]
     }
-
-    if (disable_unknown_warning_option) {
-      cflags += [ "-Wno-unknown-warning-option" ]
-    }
   }
 
   # TODO(crbug.com/354162568): Clean up and enable.
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
index cf363be5..7e56497d 100644
--- a/build/config/compiler/compiler.gni
+++ b/build/config/compiler/compiler.gni
@@ -63,9 +63,6 @@
   # With GCC, warnings in no-Chromium code are always not treated as errors.
   treat_warnings_as_errors = true
 
-  # Ignore unknown warning flags when using an older Clang version.
-  disable_unknown_warning_option = false
-
   # How clang should report warnings, either false to report in the usual
   # manner, or true to add source range information to the diagnostics in
   # a form suitable for subsequent processing with scripts. With GCC, or
diff --git a/cc/animation/BUILD.gn b/cc/animation/BUILD.gn
index a1d9ca3..9c81f755 100644
--- a/cc/animation/BUILD.gn
+++ b/cc/animation/BUILD.gn
@@ -21,6 +21,7 @@
     "animation_timeline.h",
     "animation_trigger.cc",
     "animation_trigger.h",
+    "animation_trigger_delegate.h",
     "element_animations.cc",
     "element_animations.h",
     "filter_animation_curve.cc",
diff --git a/cc/animation/animation.cc b/cc/animation/animation.cc
index e5a2032..1b272e2d 100644
--- a/cc/animation/animation.cc
+++ b/cc/animation/animation.cc
@@ -190,7 +190,8 @@
   animation_host()->RemoveFromTicking(this);
 }
 
-void Animation::DispatchAndDelegateAnimationEvent(const AnimationEvent& event) {
+void Animation::DispatchAndDelegateAnimationEvent(
+    const AnimationPlaybackEvent& event) {
   if (event.ShouldDispatchToKeyframeEffectAndModel()) {
     if (!keyframe_effect() ||
         !keyframe_effect()->DispatchAnimationEventToKeyframeModel(event)) {
@@ -204,25 +205,25 @@
   DelegateAnimationEvent(event);
 }
 
-void Animation::DelegateAnimationEvent(const AnimationEvent& event) {
+void Animation::DelegateAnimationEvent(const AnimationPlaybackEvent& event) {
   if (animation_delegate_) {
     switch (event.type) {
-      case AnimationEvent::Type::kStarted:
+      case AnimationPlaybackEvent::Type::kStarted:
         animation_delegate_->NotifyAnimationStarted(
             event.monotonic_time, event.target_property, event.group_id);
         break;
 
-      case AnimationEvent::Type::kFinished:
+      case AnimationPlaybackEvent::Type::kFinished:
         animation_delegate_->NotifyAnimationFinished(
             event.monotonic_time, event.target_property, event.group_id);
         break;
 
-      case AnimationEvent::Type::kAborted:
+      case AnimationPlaybackEvent::Type::kAborted:
         animation_delegate_->NotifyAnimationAborted(
             event.monotonic_time, event.target_property, event.group_id);
         break;
 
-      case AnimationEvent::Type::kTakeOver:
+      case AnimationPlaybackEvent::Type::kTakeOver:
         // TODO(crbug.com/40655283): Routing TAKEOVER events is broken.
         DCHECK(!event.is_impl_only);
         DCHECK(event.target_property == TargetProperty::SCROLL_OFFSET);
@@ -232,7 +233,7 @@
             event.animation_start_time, event.curve->Clone());
         break;
 
-      case AnimationEvent::Type::kTimeUpdated:
+      case AnimationPlaybackEvent::Type::kTimeUpdated:
         DCHECK(!event.is_impl_only);
         animation_delegate_->NotifyLocalTimeUpdated(event.local_time);
         break;
@@ -333,9 +334,9 @@
     int keyframe_model_id,
     TargetProperty::Type target_property,
     int group_id) {
-  AnimationEvent event(AnimationEvent::Type::kFinished,
-                       {timeline_id, id(), keyframe_model_id}, group_id,
-                       target_property, base::TimeTicks());
+  AnimationPlaybackEvent event(AnimationPlaybackEvent::Type::kFinished,
+                               {timeline_id, id(), keyframe_model_id}, group_id,
+                               target_property, base::TimeTicks());
   DispatchAndDelegateAnimationEvent(event);
 }
 
diff --git a/cc/animation/animation.h b/cc/animation/animation.h
index f2812db..35b2353a 100644
--- a/cc/animation/animation.h
+++ b/cc/animation/animation.h
@@ -26,7 +26,7 @@
 class AnimationHost;
 class AnimationTimeline;
 class KeyframeEffect;
-struct AnimationEvent;
+struct AnimationPlaybackEvent;
 
 // An Animation is responsible for managing animating properties for a set of
 // targets. Each target is represented by a KeyframeEffect and can be animating
@@ -125,7 +125,7 @@
   // appropriate, based on the event characteristics.
   // Delegates animation event that was successfully dispatched or doesn't need
   // to be dispatched.
-  void DispatchAndDelegateAnimationEvent(const AnimationEvent& event);
+  void DispatchAndDelegateAnimationEvent(const AnimationPlaybackEvent& event);
 
   // Returns true if this animation effects pending tree, such as a custom
   // property animation with paint worklet.
@@ -169,7 +169,7 @@
   void UnregisterAnimation();
 
   // Delegates animation event
-  void DelegateAnimationEvent(const AnimationEvent& event);
+  void DelegateAnimationEvent(const AnimationPlaybackEvent& event);
 
   // Common code between AttachElement and AttachNoElement.
   void AttachElementInternal(ElementId element_id);
diff --git a/cc/animation/animation_events.cc b/cc/animation/animation_events.cc
index ef2f41b..dd40bb2 100644
--- a/cc/animation/animation_events.cc
+++ b/cc/animation/animation_events.cc
@@ -6,11 +6,12 @@
 
 namespace cc {
 
-AnimationEvent::AnimationEvent(AnimationEvent::Type type,
-                               UniqueKeyframeModelId uid,
-                               int group_id,
-                               int target_property,
-                               base::TimeTicks monotonic_time)
+AnimationPlaybackEvent::AnimationPlaybackEvent(
+    AnimationPlaybackEvent::Type type,
+    UniqueKeyframeModelId uid,
+    int group_id,
+    int target_property,
+    base::TimeTicks monotonic_time)
     : type(type),
       uid(uid),
       group_id(group_id),
@@ -19,9 +20,10 @@
       is_impl_only(false),
       local_time() {}
 
-AnimationEvent::AnimationEvent(int timeline_id,
-                               int animation_id,
-                               std::optional<base::TimeDelta> local_time)
+AnimationPlaybackEvent::AnimationPlaybackEvent(
+    int timeline_id,
+    int animation_id,
+    std::optional<base::TimeDelta> local_time)
     : type(Type::kTimeUpdated),
       // Initializing model_id with an invalid value (0).
       // Also initializing keyframe_id with 0 which in its case is a valid
@@ -34,7 +36,8 @@
       is_impl_only(false),
       local_time(local_time) {}
 
-AnimationEvent::AnimationEvent(const AnimationEvent& other) {
+AnimationPlaybackEvent::AnimationPlaybackEvent(
+    const AnimationPlaybackEvent& other) {
   type = other.type;
   uid = other.uid;
   group_id = other.group_id;
@@ -47,7 +50,8 @@
   local_time = other.local_time;
 }
 
-AnimationEvent& AnimationEvent::operator=(const AnimationEvent& other) {
+AnimationPlaybackEvent& AnimationPlaybackEvent::operator=(
+    const AnimationPlaybackEvent& other) {
   type = other.type;
   uid = other.uid;
   group_id = other.group_id;
@@ -61,7 +65,7 @@
   return *this;
 }
 
-AnimationEvent::~AnimationEvent() = default;
+AnimationPlaybackEvent::~AnimationPlaybackEvent() = default;
 
 AnimationEvents::AnimationEvents() : needs_time_updated_events_(false) {}
 
@@ -71,7 +75,7 @@
   return events().empty() && !needs_time_updated_events_;
 }
 
-bool AnimationEvent::ShouldDispatchToKeyframeEffectAndModel() const {
+bool AnimationPlaybackEvent::ShouldDispatchToKeyframeEffectAndModel() const {
   // TIME_UPDATED events are used to synchronize effect time between cc and
   // main thread worklet animations. Keyframe models are not involved in
   // this process.
@@ -80,4 +84,13 @@
   return type != Type::kTimeUpdated && !is_impl_only;
 }
 
+AnimationTriggerEvent::AnimationTriggerEvent(int trigger_id, Type type)
+    : trigger_id(trigger_id), type(type) {}
+
+AnimationTriggerEvent::AnimationTriggerEvent(
+    const AnimationTriggerEvent& other) {
+  type = other.type;
+  trigger_id = other.trigger_id;
+}
+
 }  // namespace cc
diff --git a/cc/animation/animation_events.h b/cc/animation/animation_events.h
index d1401a82..cd66bb8 100644
--- a/cc/animation/animation_events.h
+++ b/cc/animation/animation_events.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include <optional>
+#include <variant>
 #include <vector>
 
 #include "base/time/time.h"
@@ -16,7 +17,7 @@
 
 namespace cc {
 
-struct CC_ANIMATION_EXPORT AnimationEvent {
+struct CC_ANIMATION_EXPORT AnimationPlaybackEvent {
   enum class Type { kStarted, kFinished, kAborted, kTakeOver, kTimeUpdated };
 
   typedef size_t KeyframeEffectId;
@@ -26,21 +27,21 @@
     int model_id;
   };
 
-  AnimationEvent(Type type,
-                 UniqueKeyframeModelId uid,
-                 int group_id,
-                 int target_property,
-                 base::TimeTicks monotonic_time);
+  AnimationPlaybackEvent(Type type,
+                         UniqueKeyframeModelId uid,
+                         int group_id,
+                         int target_property,
+                         base::TimeTicks monotonic_time);
 
-  // Constructs AnimationEvent of TIME_UPDATED type.
-  AnimationEvent(int timeline_id,
-                 int animation_id,
-                 std::optional<base::TimeDelta> local_time);
+  // Constructs AnimationPlaybackEvent of TIME_UPDATED type.
+  AnimationPlaybackEvent(int timeline_id,
+                         int animation_id,
+                         std::optional<base::TimeDelta> local_time);
 
-  AnimationEvent(const AnimationEvent& other);
-  AnimationEvent& operator=(const AnimationEvent& other);
+  AnimationPlaybackEvent(const AnimationPlaybackEvent& other);
+  AnimationPlaybackEvent& operator=(const AnimationPlaybackEvent& other);
 
-  ~AnimationEvent();
+  ~AnimationPlaybackEvent();
 
   bool ShouldDispatchToKeyframeEffectAndModel() const;
 
@@ -55,10 +56,25 @@
   base::TimeTicks animation_start_time;
   std::unique_ptr<gfx::AnimationCurve> curve;
 
-  // Set for TIME_UPDATED events.
   std::optional<base::TimeDelta> local_time;
 };
 
+// This describes the occurrence of an event for an animation-trigger[1]
+// that occurs on the impl thread.
+// [1] https://drafts.csswg.org/css-animations-2/#animation-triggers
+struct CC_ANIMATION_EXPORT AnimationTriggerEvent {
+  enum class Type {
+    kActivate,
+    kDeactivate,
+  };
+
+  AnimationTriggerEvent(int trigger_id, Type type);
+  AnimationTriggerEvent(const AnimationTriggerEvent& other);
+
+  int trigger_id;
+  Type type;
+};
+
 class CC_ANIMATION_EXPORT AnimationEvents : public MutatorEvents {
  public:
   AnimationEvents();
@@ -72,11 +88,13 @@
     needs_time_updated_events_ = value;
   }
 
-  const std::vector<AnimationEvent>& events() const { return events_; }
-  std::vector<AnimationEvent>& events() { return events_; }
+  using Event = std::variant<AnimationPlaybackEvent, AnimationTriggerEvent>;
+
+  const std::vector<Event>& events() const { return events_; }
+  std::vector<Event>& events() { return events_; }
 
  private:
-  std::vector<AnimationEvent> events_;
+  std::vector<Event> events_;
   bool needs_time_updated_events_ = false;
 };
 
diff --git a/cc/animation/animation_host.cc b/cc/animation/animation_host.cc
index 2965676..f55272ee 100644
--- a/cc/animation/animation_host.cc
+++ b/cc/animation/animation_host.cc
@@ -27,6 +27,7 @@
 #include "cc/animation/scroll_offset_animations.h"
 #include "cc/animation/scroll_offset_animations_impl.h"
 #include "cc/animation/scroll_timeline.h"
+#include "cc/animation/timeline_trigger.h"
 #include "cc/animation/worklet_animation.h"
 #include "ui/gfx/animation/keyframe/timing_function.h"
 #include "ui/gfx/geometry/vector2d_f.h"
@@ -649,7 +650,8 @@
 
 bool AnimationHost::TickAnimations(base::TimeTicks monotonic_time,
                                    const ScrollTree& scroll_tree,
-                                   bool is_active_tree) {
+                                   bool is_active_tree,
+                                   MutatorEvents* mutator_events) {
   TRACE_EVENT0("cc", "AnimationHost::TickAnimations");
   // We tick animations in the following order:
   // 1. regular animations 2. mutator 3. worklet animations
@@ -666,7 +668,15 @@
 
   TRACE_EVENT_INSTANT0("cc", "NeedsTickAnimations", TRACE_EVENT_SCOPE_THREAD);
 
+  if (is_active_tree) {
+    // We update triggers first since they affect whether an animation is in
+    // effect or not.
+    auto* animation_events = static_cast<AnimationEvents*>(mutator_events);
+    UpdateTriggers(scroll_tree, animation_events);
+  }
+
   bool animated = false;
+
   std::vector<AnimationTimeline*> scroll_timelines;
   for (auto& kv : id_to_timeline_map_.Read(*this)) {
     AnimationTimeline* timeline = kv.second.get();
@@ -739,6 +749,7 @@
   auto* animation_events = static_cast<AnimationEvents*>(mutator_events);
 
   TRACE_EVENT0("cc", "AnimationHost::UpdateAnimationState");
+
   AnimationsList ticking_animations_copy = ticking_animations_.Read(*this);
   for (auto& it : ticking_animations_copy)
     it->UpdateState(start_ready_animations, animation_events);
@@ -774,12 +785,26 @@
   auto events =
       base::WrapUnique(static_cast<AnimationEvents*>(mutator_events.release()));
 
-  for (const AnimationEvent& event : events->events()) {
-    AnimationTimeline* timeline = GetTimelineById(event.uid.timeline_id);
-    if (timeline) {
-      Animation* animation = timeline->GetAnimationById(event.uid.animation_id);
-      if (animation)
-        animation->DispatchAndDelegateAnimationEvent(event);
+  for (const AnimationEvents::Event& event : events->events()) {
+    if (const auto* playback_event =
+            std::get_if<AnimationPlaybackEvent>(&event)) {
+      AnimationTimeline* timeline =
+          GetTimelineById(playback_event->uid.timeline_id);
+      if (timeline) {
+        Animation* animation =
+            timeline->GetAnimationById(playback_event->uid.animation_id);
+        if (animation) {
+          animation->DispatchAndDelegateAnimationEvent(*playback_event);
+        }
+      }
+    } else if (const auto* trigger_event =
+                   std::get_if<AnimationTriggerEvent>(&event)) {
+      AnimationTrigger* trigger = GetTriggerById(trigger_event->trigger_id);
+      if (trigger) {
+        trigger->DispatchAnimationTriggerEvent(*trigger_event);
+      }
+    } else {
+      NOTREACHED();  // Unhandled animation event type.
     }
   }
 }
@@ -1047,4 +1072,14 @@
   return false;
 }
 
+void AnimationHost::UpdateTriggers(const ScrollTree& scroll_tree,
+                                   AnimationEvents* events) const {
+  for (const auto& kv : id_to_trigger_map_.Read(*this)) {
+    AnimationTrigger* trigger = kv.second.get();
+    // NOTE(crbug.com/451238244): Only timeline triggers are supported for now.
+    DCHECK(trigger->IsTimelineTrigger());
+    static_cast<TimelineTrigger*>(trigger)->Update(scroll_tree, events);
+  }
+}
+
 }  // namespace cc
diff --git a/cc/animation/animation_host.h b/cc/animation/animation_host.h
index 84c34395..c9c54d9 100644
--- a/cc/animation/animation_host.h
+++ b/cc/animation/animation_host.h
@@ -25,6 +25,7 @@
 namespace cc {
 
 class Animation;
+class AnimationEvents;
 class AnimationTrigger;
 class AnimationTimeline;
 class ElementAnimations;
@@ -147,7 +148,8 @@
   bool ActivateAnimations(MutatorEvents* events) override;
   bool TickAnimations(base::TimeTicks monotonic_time,
                       const ScrollTree& scroll_tree,
-                      bool is_active_tree) override;
+                      bool is_active_tree,
+                      MutatorEvents* events) override;
   void TickScrollAnimations(base::TimeTicks monotonic_time,
                             const ScrollTree& scroll_tree) override;
   void TickWorkletAnimations() override;
@@ -288,6 +290,11 @@
                    const ScrollTree& scroll_tree,
                    bool is_active_tree);
 
+  // Update animation triggers[1].
+  // [1] https://drafts.csswg.org/web-animations/#animation-triggers
+  void UpdateTriggers(const ScrollTree& scroll_tree,
+                      AnimationEvents* events) const;
+
   // Return the state representing all ticking worklet animations.
   std::unique_ptr<MutatorInputState> CollectWorkletAnimationsState(
       base::TimeTicks timeline_time,
diff --git a/cc/animation/animation_host_unittest.cc b/cc/animation/animation_host_unittest.cc
index ae80d71..115e689 100644
--- a/cc/animation/animation_host_unittest.cc
+++ b/cc/animation/animation_host_unittest.cc
@@ -391,7 +391,7 @@
   // reflected in the input of the layer tree mutator in the same animation
   // frame.
   host_impl_->TickAnimations(base::TimeTicks(), property_trees.scroll_tree(),
-                             false);
+                             false, nullptr);
 }
 
 TEST_F(AnimationHostTest, TickScrollLinkedAnimation) {
@@ -426,8 +426,8 @@
 
   const auto& scroll_tree = property_trees.scroll_tree();
   SetScrollOffset(&property_trees, element_id_, gfx::PointF(0, 20));
-  EXPECT_TRUE(
-      host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false));
+  EXPECT_TRUE(host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false,
+                                         nullptr));
 
   EXPECT_EQ(keyframe_model->run_state(), KeyframeModel::STARTING);
   double tick_time =
@@ -436,8 +436,8 @@
       ToMilliseconds(scroll_timeline->Duration(scroll_tree, false));
   EXPECT_NEAR(tick_time, 0.2 * duration, 1e-6);
   scroll_timeline->DetachAnimation(animation);
-  EXPECT_FALSE(
-      host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false));
+  EXPECT_FALSE(host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false,
+                                          nullptr));
 }
 
 TEST_F(AnimationHostTest, TickScrollLinkedAnimationNonCompositedScroll) {
@@ -473,8 +473,8 @@
 
   auto& scroll_tree = property_trees.scroll_tree_mutable();
   SetScrollOffset(&property_trees, element_id_, gfx::PointF(0, 20));
-  EXPECT_TRUE(
-      host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false));
+  EXPECT_TRUE(host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false,
+                                         nullptr));
 
   EXPECT_EQ(keyframe_model->run_state(), KeyframeModel::STARTING);
   double tick_time = (scroll_timeline->CurrentTime(scroll_tree, false).value() -
@@ -486,16 +486,16 @@
   // Simulate that the main thread commits a different scroll offset.
   synced_offset->PushMainToPending(gfx::PointF(0, 10));
   synced_offset->PushPendingToActive();
-  EXPECT_TRUE(
-      host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false));
+  EXPECT_TRUE(host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false,
+                                         nullptr));
   tick_time = ToMilliseconds(scroll_timeline->CurrentTime(scroll_tree, false));
   double duration =
       ToMilliseconds(scroll_timeline->Duration(scroll_tree, false));
   EXPECT_NEAR(tick_time, 0.1 * duration, 1e-6);
 
   scroll_timeline->DetachAnimation(animation);
-  EXPECT_FALSE(
-      host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false));
+  EXPECT_FALSE(host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false,
+                                          nullptr));
 }
 
 TEST_F(AnimationHostTest, TickScrollLinkedAnimationSmooth) {
@@ -528,7 +528,7 @@
   auto* keyframe_model = animation->GetKeyframeModel(TargetProperty::OPACITY);
   keyframe_model->set_needs_synchronized_start_time(false);
 
-  host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false);
+  host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false, nullptr);
   TickAnimationsTransferEvents(base::TimeTicks(), 1u);
 
   scoped_refptr<MockAnimation> mock_scroll_animation(
@@ -543,7 +543,7 @@
 
   // This should tick the scroll animation first, and then the opacity animation
   // that depends on the scroll position.
-  host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false);
+  host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false, nullptr);
 
   const float expected_opacity = 0.5;
   client_impl_.ExpectOpacityPropertyMutated(element_id, ElementListType::ACTIVE,
@@ -597,7 +597,7 @@
       element_id_, ScrollTimeline::ScrollDown, scroll_offsets);
 
   host_impl_->TickAnimations(base::TimeTicks(), property_trees.scroll_tree(),
-                             false);
+                             false, nullptr);
 
   double tick_time = ToMilliseconds(
       scroll_timeline->CurrentTime(property_trees.scroll_tree(), false));
diff --git a/cc/animation/animation_trigger.cc b/cc/animation/animation_trigger.cc
index 21bde85..4021d5d 100644
--- a/cc/animation/animation_trigger.cc
+++ b/cc/animation/animation_trigger.cc
@@ -8,6 +8,7 @@
 
 #include "cc/animation/animation_host.h"
 #include "cc/animation/animation_timeline.h"
+#include "cc/animation/animation_trigger_delegate.h"
 #include "cc/animation/keyframe_effect.h"
 
 namespace cc {
@@ -78,4 +79,36 @@
   }
 }
 
+void AnimationTrigger::PerformActivate(AnimationEvents* events) {
+  DCHECK(events);
+  events->events().emplace_back(
+      AnimationTriggerEvent(id(), AnimationTriggerEvent::Type::kActivate));
+  // TODO(crbug.com/451238244): Trigger animations.
+}
+
+void AnimationTrigger::PerformDeactivate(AnimationEvents* events) {
+  DCHECK(events);
+  events->events().emplace_back(
+      AnimationTriggerEvent(id(), AnimationTriggerEvent::Type::kDeactivate));
+  // TODO(crbug.com/451238244): Trigger animations.
+}
+
+void AnimationTrigger::SetAnimationTriggerDelegate(
+    AnimationTriggerDelegate* delegate) {
+  animation_trigger_delegate_ = delegate;
+}
+
+void AnimationTrigger::DispatchAnimationTriggerEvent(
+    const AnimationTriggerEvent& event) {
+  if (animation_trigger_delegate_) {
+    switch (event.type) {
+      case AnimationTriggerEvent::Type::kActivate:
+        animation_trigger_delegate_->NotifyActivated();
+        break;
+      case AnimationTriggerEvent::Type::kDeactivate:
+        animation_trigger_delegate_->NotifyDeactivated();
+    }
+  }
+}
+
 }  // namespace cc
diff --git a/cc/animation/animation_trigger.h b/cc/animation/animation_trigger.h
index 1f3ea62..98a65fd 100644
--- a/cc/animation/animation_trigger.h
+++ b/cc/animation/animation_trigger.h
@@ -15,19 +15,33 @@
 
 namespace cc {
 
+class AnimationEvents;
 class AnimationHost;
+class AnimationTriggerDelegate;
+struct AnimationTriggerEvent;
 
 // An AnimationTrigger controls the playback of its associated Animations by
 // invoking the Animation playback control methods. Each AnimationTrigger
-// determines when to invoke these methods based on how the trigger's conditions
-// are set up, e.g. a TimelineTrigger acts on its animations based on the entry
-// and the exit of portions of its timelines while an EventTrigger acts on its
-// associated animations when the UIEvents with which the trigger was
-// constructed occur.
+// determines when to invoke these methods based on how the trigger's
+// conditions are set up, e.g. a TimelineTrigger acts on its animations
+// based on the entry and the exit of portions of its timelines while an
+// EventTrigger acts on its associated animations when the UIEvents with
+// which the trigger was constructed occur.
 class CC_ANIMATION_EXPORT AnimationTrigger
     : public base::RefCounted<AnimationTrigger>,
       public ProtectedSequenceSynchronizer {
  public:
+  enum class State {
+    // "activate" condition has never been met.
+    kIdle,
+    // "activate" condition has been met and no "deactivate" condition has been
+    // met since the last "activate" condition was met.
+    kPrimary,
+    // "deactivate" condition has been met and no "activate" condition has been
+    // met since the last "deactivate" condition was met.
+    kInverse,
+  };
+
   enum class Behavior {
     kPlay,
     kPause,
@@ -86,6 +100,17 @@
   void PushPropertiesTo(AnimationTrigger* trigger_impl);
   void SetNeedsPushProperties();
 
+  // Perform the relevant actions for the associated animations based on the
+  // trigger's state.
+  void PerformActivate(AnimationEvents* events);
+  void PerformDeactivate(AnimationEvents* events);
+
+  void SetAnimationTriggerDelegate(AnimationTriggerDelegate* delegate);
+
+  // Dispatches animation trigger events (activate/deactivate) to the
+  // animation trigger delegate (the main thread trigger).
+  void DispatchAnimationTriggerEvent(const AnimationTriggerEvent& event);
+
  protected:
   explicit AnimationTrigger(int id);
   ~AnimationTrigger() override;
@@ -97,6 +122,8 @@
 
   raw_ptr<AnimationHost> animation_host_;
   ProtectedSequenceReadable<std::vector<AnimationData>> animation_data_;
+  // The main thread trigger listening for compositor-initiated trigger events.
+  raw_ptr<AnimationTriggerDelegate> animation_trigger_delegate_;
 };
 
 }  // namespace cc
diff --git a/cc/animation/animation_trigger_delegate.h b/cc/animation/animation_trigger_delegate.h
new file mode 100644
index 0000000..e9889a9
--- /dev/null
+++ b/cc/animation/animation_trigger_delegate.h
@@ -0,0 +1,24 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_ANIMATION_ANIMATION_TRIGGER_DELEGATE_H_
+#define CC_ANIMATION_ANIMATION_TRIGGER_DELEGATE_H_
+
+namespace cc {
+
+// This class describes an interface to be implemented by objects
+// interested in listening to "activate" and "deactivate" events of
+// cc AnimationTriggers.
+class CC_ANIMATION_EXPORT AnimationTriggerDelegate {
+ public:
+  virtual void NotifyActivated() = 0;
+  virtual void NotifyDeactivated() = 0;
+
+ protected:
+  ~AnimationTriggerDelegate() = default;
+};
+
+}  // namespace cc
+
+#endif  // CC_ANIMATION_ANIMATION_TRIGGER_DELEGATE_H_
diff --git a/cc/animation/element_animations_unittest.cc b/cc/animation/element_animations_unittest.cc
index 45fb5d7..bb6a103 100644
--- a/cc/animation/element_animations_unittest.cc
+++ b/cc/animation/element_animations_unittest.cc
@@ -332,10 +332,12 @@
   auto events = CreateEventsForTesting();
   animation2_impl->UpdateState(true, events.get());
   EXPECT_EQ(1u, events->events().size());
-  EXPECT_EQ(AnimationEvent::Type::kStarted, events->events()[0].type);
+  const AnimationPlaybackEvent& event =
+      std::get<AnimationPlaybackEvent>(events->events()[0]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kStarted, event.type);
 
   // The actual detachment happens here, inside the callback
-  animation2->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  animation2->DispatchAndDelegateAnimationEvent(event);
   EXPECT_TRUE(delegate.started());
 }
 
@@ -367,7 +369,9 @@
 
   // Synchronize the start times.
   EXPECT_EQ(1u, events->events().size());
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  const AnimationPlaybackEvent& event =
+      std::get<AnimationPlaybackEvent>(events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(event);
   EXPECT_EQ(animation_->keyframe_effect()
                 ->GetKeyframeModelById(keyframe_model_id)
                 ->start_time(),
@@ -414,7 +418,9 @@
 
   // Synchronize the start times.
   EXPECT_EQ(1u, events->events().size());
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  const AnimationPlaybackEvent& event =
+      std::get<AnimationPlaybackEvent>(events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(event);
 
   EXPECT_EQ(start_time, animation_->keyframe_effect()
                             ->GetKeyframeModelById(keyframe_model_id)
@@ -471,7 +477,8 @@
   animation_impl_->Tick(kInitialTickTime);
   animation_impl_->UpdateState(true, events.get());
   EXPECT_EQ(1u, events->events().size());
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  const auto* event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
 
   EXPECT_EQ(1u, host->ticking_animations_for_testing().size());
   EXPECT_EQ(1u, host_impl->ticking_animations_for_testing().size());
@@ -499,7 +506,8 @@
   EXPECT_EQ(1u, host_impl->ticking_animations_for_testing().size());
 
   EXPECT_EQ(1u, events->events().size());
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   animation_->Tick(kInitialTickTime + base::Milliseconds(1500));
   animation_->UpdateState(true, nullptr);
 
@@ -553,7 +561,9 @@
 
   animation_->Tick(time);
   animation_->UpdateState(true, nullptr);
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  const AnimationPlaybackEvent& event =
+      std::get<AnimationPlaybackEvent>(events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(event);
 
   EXPECT_EQ(KeyframeModel::RUNNING,
             animation_impl_->keyframe_effect()
@@ -627,19 +637,21 @@
   animation_impl_->Tick(kInitialTickTime);
   animation_impl_->UpdateState(true, events.get());
   EXPECT_EQ(1u, events->events().size());
-  EXPECT_EQ(AnimationEvent::Type::kStarted, events->events()[0].type);
+  const auto* event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kStarted, event->type);
 
   // Notify main thread animations that the animation has started.
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
 
   // Complete animation on impl thread.
   events = CreateEventsForTesting();
   animation_impl_->Tick(kInitialTickTime + base::Seconds(1));
   animation_impl_->UpdateState(true, events.get());
   EXPECT_EQ(1u, events->events().size());
-  EXPECT_EQ(AnimationEvent::Type::kFinished, events->events()[0].type);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kFinished, event->type);
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
 
   animation_->Tick(kInitialTickTime + base::Seconds(2));
   animation_->UpdateState(true, nullptr);
@@ -678,8 +690,9 @@
 
   // There should be a STARTED event for the animation.
   EXPECT_EQ(1u, events->events().size());
-  EXPECT_EQ(AnimationEvent::Type::kStarted, events->events()[0].type);
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  const auto* event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kStarted, event->type);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
 
   animation_->Tick(kInitialTickTime + base::Milliseconds(1000));
   animation_->UpdateState(true, nullptr);
@@ -694,13 +707,14 @@
 
   // There should be a FINISHED event for the animation.
   EXPECT_EQ(1u, events->events().size());
-  EXPECT_EQ(AnimationEvent::Type::kFinished, events->events()[0].type);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kFinished, event->type);
 
   // Neither animations should have deleted the animation yet.
   EXPECT_TRUE(animation_->GetKeyframeModel(TargetProperty::OPACITY));
   EXPECT_TRUE(animation_impl_->GetKeyframeModel(TargetProperty::OPACITY));
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
 
   animation_->Tick(kInitialTickTime + base::Milliseconds(3000));
   animation_->UpdateState(true, nullptr);
@@ -740,8 +754,9 @@
 
   // There should be a STARTED event for the animation.
   EXPECT_EQ(1u, events->events().size());
-  EXPECT_EQ(AnimationEvent::Type::kStarted, events->events()[0].type);
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  const auto* event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kStarted, event->type);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
 
   events = CreateEventsForTesting();
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(2000));
@@ -751,7 +766,8 @@
 
   // There should be a FINISHED event for the animation.
   EXPECT_EQ(1u, events->events().size());
-  EXPECT_EQ(AnimationEvent::Type::kFinished, events->events()[0].type);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kFinished, event->type);
 
   // Before the FINISHED event is received, main aborts the keyframe
   // and detaches the element.
@@ -762,7 +778,7 @@
   EXPECT_FALSE(animation_->keyframe_effect()->has_any_keyframe_model());
 
   // Then we dispatch the FINISHED event.
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
 
   EXPECT_TRUE(host_->needs_push_properties());
 
@@ -953,7 +969,9 @@
   EXPECT_EQ(initial_value,
             client_impl_.GetScrollOffset(element_id_, ElementListType::ACTIVE));
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  const AnimationPlaybackEvent& event =
+      std::get<AnimationPlaybackEvent>(events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(event);
   animation_->Tick(kInitialTickTime + duration / 2);
   animation_->UpdateState(true, nullptr);
   EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel());
@@ -1133,7 +1151,9 @@
   animation_impl_->UpdateState(true, events.get());
   DCHECK_EQ(1UL, events->events().size());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  const AnimationPlaybackEvent& event =
+      std::get<AnimationPlaybackEvent>(events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(event);
   animation_->Tick(kInitialTickTime + duration / 2);
   animation_->UpdateState(true, nullptr);
   EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel());
@@ -1363,7 +1383,9 @@
 
   // Synchronize the start times.
   EXPECT_EQ(1u, events->events().size());
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  const AnimationPlaybackEvent& event =
+      std::get<AnimationPlaybackEvent>(events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(event);
 
   // Validate start time on the main thread delegate.
   EXPECT_EQ(start_time, delegate.start_time());
@@ -1401,8 +1423,8 @@
   EXPECT_EQ(0.f, client_.GetOpacity(element_id_, ElementListType::ACTIVE));
 
   // Send the synchronized start time.
-  animation_->DispatchAndDelegateAnimationEvent(AnimationEvent(
-      AnimationEvent::Type::kStarted,
+  animation_->DispatchAndDelegateAnimationEvent(AnimationPlaybackEvent(
+      AnimationPlaybackEvent::Type::kStarted,
       {animation_->animation_timeline()->id(), animation_->id(),
        keyframe_model_id},
       1, TargetProperty::OPACITY, kInitialTickTime + base::Milliseconds(2000)));
@@ -1817,7 +1839,11 @@
 
   // Should have one STARTED event and one FINISHED event.
   EXPECT_EQ(2u, events->events().size());
-  EXPECT_NE(events->events()[0].type, events->events()[1].type);
+  const AnimationPlaybackEvent& event0 =
+      std::get<AnimationPlaybackEvent>(events->events()[0]);
+  const AnimationPlaybackEvent& event1 =
+      std::get<AnimationPlaybackEvent>(events->events()[1]);
+  EXPECT_NE(event0.type, event1.type);
 
   // The float transition should still be at its starting point.
   EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel());
@@ -2033,12 +2059,14 @@
   animation_impl_->UpdateState(true, events.get());
   EXPECT_TRUE(host_impl_->needs_push_properties());
   EXPECT_EQ(1u, events->events().size());
-  EXPECT_EQ(AnimationEvent::Type::kAborted, events->events()[0].type);
+  const AnimationPlaybackEvent& event =
+      std::get<AnimationPlaybackEvent>(events->events()[0]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kAborted, event.type);
   EXPECT_EQ(
       KeyframeModel::WAITING_FOR_DELETION,
       animation_impl_->GetKeyframeModel(TargetProperty::OPACITY)->run_state());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(event);
   EXPECT_EQ(KeyframeModel::ABORTED,
             animation_->GetKeyframeModel(TargetProperty::OPACITY)->run_state());
   EXPECT_TRUE(delegate.aborted());
@@ -2105,16 +2133,18 @@
   EXPECT_TRUE(delegate_impl.finished());
   EXPECT_TRUE(host_impl_->needs_push_properties());
   EXPECT_EQ(1u, events->events().size());
-  EXPECT_EQ(AnimationEvent::Type::kTakeOver, events->events()[0].type);
-  EXPECT_EQ(TicksFromSecondsF(123), events->events()[0].animation_start_time);
-  EXPECT_EQ(target_value, static_cast<ScrollOffsetAnimationCurve*>(
-                              events->events()[0].curve.get())
-                              ->target_value());
+  const AnimationPlaybackEvent& event =
+      std::get<AnimationPlaybackEvent>(events->events()[0]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kTakeOver, event.type);
+  EXPECT_EQ(TicksFromSecondsF(123), event.animation_start_time);
+  EXPECT_EQ(target_value,
+            static_cast<ScrollOffsetAnimationCurve*>(event.curve.get())
+                ->target_value());
   EXPECT_EQ(nullptr,
             animation_impl_->GetKeyframeModel(TargetProperty::SCROLL_OFFSET));
 
   // MT receives the event to take over.
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(event);
   EXPECT_TRUE(delegate.takeover());
 
   // Animation::NotifyAnimationTakeover requests SetNeedsPushProperties to purge
@@ -2161,8 +2191,12 @@
 
   // Both animations should have started.
   EXPECT_EQ(2u, events->events().size());
-  EXPECT_EQ(AnimationEvent::Type::kStarted, events->events()[0].type);
-  EXPECT_EQ(AnimationEvent::Type::kStarted, events->events()[1].type);
+  const auto* event0 =
+      std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  const auto* event1 =
+      std::get_if<AnimationPlaybackEvent>(&events->events()[1]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kStarted, event0->type);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kStarted, event1->type);
 
   events = CreateEventsForTesting();
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(1000));
@@ -2183,8 +2217,11 @@
 
   // Both animations should have generated FINISHED events.
   EXPECT_EQ(2u, events->events().size());
-  EXPECT_EQ(AnimationEvent::Type::kFinished, events->events()[0].type);
-  EXPECT_EQ(AnimationEvent::Type::kFinished, events->events()[1].type);
+
+  event0 = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  event1 = std::get_if<AnimationPlaybackEvent>(&events->events()[1]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kFinished, event0->type);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kFinished, event1->type);
 }
 
 // Ensure that when a group has a mix of aborted and finished animations,
@@ -2215,8 +2252,12 @@
 
   // Both animations should have started.
   EXPECT_EQ(2u, events->events().size());
-  EXPECT_EQ(AnimationEvent::Type::kStarted, events->events()[0].type);
-  EXPECT_EQ(AnimationEvent::Type::kStarted, events->events()[1].type);
+  const auto* event0 =
+      std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  const auto* event1 =
+      std::get_if<AnimationPlaybackEvent>(&events->events()[1]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kStarted, event0->type);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kStarted, event1->type);
 
   animation_impl_->AbortKeyframeModelsWithProperty(TargetProperty::OPACITY,
                                                    false);
@@ -2228,10 +2269,12 @@
   // We should have exactly 2 events: a FINISHED event for the tranform
   // animation, and an ABORTED event for the opacity animation.
   EXPECT_EQ(2u, events->events().size());
-  EXPECT_EQ(AnimationEvent::Type::kFinished, events->events()[0].type);
-  EXPECT_EQ(TargetProperty::TRANSFORM, events->events()[0].target_property);
-  EXPECT_EQ(AnimationEvent::Type::kAborted, events->events()[1].type);
-  EXPECT_EQ(TargetProperty::OPACITY, events->events()[1].target_property);
+  event0 = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  event1 = std::get_if<AnimationPlaybackEvent>(&events->events()[1]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kFinished, event0->type);
+  EXPECT_EQ(TargetProperty::TRANSFORM, event0->target_property);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kAborted, event1->type);
+  EXPECT_EQ(TargetProperty::OPACITY, event1->target_property);
 }
 
 TEST_F(ElementAnimationsTest, MaximumAnimationScaleNotScaled) {
@@ -2701,7 +2744,8 @@
   animation_impl_->Tick(kInitialTickTime);
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  const auto* event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   events->events().clear();
 
   // Finish the animation.
@@ -2774,7 +2818,8 @@
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(2000));
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   events->events().clear();
 
   animation_->RemoveKeyframeModel(keyframe_model_id);
@@ -2827,7 +2872,8 @@
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(2000));
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   events->events().clear();
 
   animation_impl_->AbortKeyframeModelsWithProperty(TargetProperty::TRANSFORM,
@@ -2844,7 +2890,8 @@
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(4000));
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   EXPECT_FALSE(client_.GetHasPotentialTransformAnimation(
       element_id_, ElementListType::ACTIVE));
   EXPECT_FALSE(client_.GetTransformIsCurrentlyAnimating(
@@ -2928,7 +2975,8 @@
   animation_impl_->Tick(kInitialTickTime);
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  const auto* event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   events->events().clear();
 
   // Finish the animation.
@@ -2990,7 +3038,8 @@
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(2000));
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   events->events().clear();
 
   animation_->RemoveKeyframeModel(keyframe_model_id);
@@ -3042,7 +3091,8 @@
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(2000));
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   events->events().clear();
 
   animation_impl_->AbortKeyframeModelsWithProperty(TargetProperty::OPACITY,
@@ -3059,7 +3109,8 @@
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(4000));
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   EXPECT_FALSE(client_.GetHasPotentialOpacityAnimation(
       element_id_, ElementListType::ACTIVE));
   EXPECT_FALSE(client_.GetOpacityIsCurrentlyAnimating(element_id_,
@@ -3142,7 +3193,8 @@
   animation_impl_->Tick(kInitialTickTime);
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  const auto* event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   events->events().clear();
 
   // Finish the animation.
@@ -3204,7 +3256,8 @@
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(2000));
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   events->events().clear();
 
   animation_->RemoveKeyframeModel(keyframe_model_id);
@@ -3256,7 +3309,8 @@
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(2000));
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   events->events().clear();
 
   animation_impl_->AbortKeyframeModelsWithProperty(TargetProperty::FILTER,
@@ -3273,7 +3327,8 @@
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(4000));
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   EXPECT_FALSE(client_.GetHasPotentialFilterAnimation(element_id_,
                                                       ElementListType::ACTIVE));
   EXPECT_FALSE(client_.GetFilterIsCurrentlyAnimating(element_id_,
@@ -3357,7 +3412,8 @@
   animation_impl_->Tick(kInitialTickTime);
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  const auto* event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   events->events().clear();
 
   // Finish the animation.
@@ -3419,7 +3475,8 @@
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(2000));
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   events->events().clear();
 
   animation_->RemoveKeyframeModel(keyframe_model_id);
@@ -3471,7 +3528,8 @@
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(2000));
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   events->events().clear();
 
   animation_impl_->AbortKeyframeModelsWithProperty(
@@ -3488,7 +3546,8 @@
   animation_impl_->Tick(kInitialTickTime + base::Milliseconds(4000));
   animation_impl_->UpdateState(true, events.get());
 
-  animation_->DispatchAndDelegateAnimationEvent(events->events()[0]);
+  event = std::get_if<AnimationPlaybackEvent>(&events->events()[0]);
+  animation_->DispatchAndDelegateAnimationEvent(*event);
   EXPECT_FALSE(client_.GetHasPotentialBackdropFilterAnimation(
       element_id_, ElementListType::ACTIVE));
   EXPECT_FALSE(client_.GetBackdropFilterIsCurrentlyAnimating(
diff --git a/cc/animation/keyframe_effect.cc b/cc/animation/keyframe_effect.cc
index 267462e..2fe7b13 100644
--- a/cc/animation/keyframe_effect.cc
+++ b/cc/animation/keyframe_effect.cc
@@ -413,13 +413,13 @@
 }
 
 bool KeyframeEffect::DispatchAnimationEventToKeyframeModel(
-    const AnimationEvent& event) {
+    const AnimationPlaybackEvent& event) {
   DCHECK(!event.is_impl_only);
   KeyframeModel* keyframe_model = KeyframeModel::ToCcKeyframeModel(
       GetKeyframeModelById(event.uid.model_id));
   bool dispatched = false;
   switch (event.type) {
-    case AnimationEvent::Type::kStarted:
+    case AnimationPlaybackEvent::Type::kStarted:
       if (!keyframe_model) {
         KeyframeModel* replacement = KeyframeModel::ToCcKeyframeModel(
             GetKeyframeModel(event.target_property));
@@ -435,7 +435,7 @@
       }
       break;
 
-    case AnimationEvent::Type::kFinished:
+    case AnimationPlaybackEvent::Type::kFinished:
       if (keyframe_model) {
         keyframe_model->set_received_finished_event(true);
         dispatched = true;
@@ -448,7 +448,7 @@
       }
       break;
 
-    case AnimationEvent::Type::kAborted:
+    case AnimationPlaybackEvent::Type::kAborted:
       if (keyframe_model) {
         keyframe_model->SetRunState(gfx::KeyframeModel::ABORTED,
                                     event.monotonic_time);
@@ -459,14 +459,14 @@
       }
       break;
 
-    case AnimationEvent::Type::kTakeOver:
+    case AnimationPlaybackEvent::Type::kTakeOver:
       // TODO(crbug.com/40655283): Routing TAKEOVER events is broken.
       // We need to purge KeyframeModels marked for deletion on CT.
       SetNeedsPushProperties();
       dispatched = true;
       break;
 
-    case AnimationEvent::Type::kTimeUpdated:
+    case AnimationPlaybackEvent::Type::kTimeUpdated:
       // TIME_UPDATED events are used to synchronize effect time between cc and
       // main thread worklet animations. Keyframe models are not involved in
       // this process.
@@ -972,8 +972,8 @@
       else
         start_time = last_tick_time_.value_or(base::TimeTicks());
 
-      GenerateEvent(events, *cc_keyframe_model, AnimationEvent::Type::kStarted,
-                    start_time);
+      GenerateEvent(events, *cc_keyframe_model,
+                    AnimationPlaybackEvent::Type::kStarted, start_time);
     }
   }
 }
@@ -989,16 +989,16 @@
   };
 
   // Non-aborted KeyframeModels are marked for deletion after a corresponding
-  // AnimationEvent::Type::kFinished event is sent or received. This means that
-  // if we don't have an events vector, we must ensure that non-aborted
-  // KeyframeModels have received a finished event before marking them for
-  // deletion.
+  // AnimationPlaybackEvent::Type::kFinished event is sent or received. This
+  // means that if we don't have an events vector, we must ensure that
+  // non-aborted KeyframeModels have received a finished event before marking
+  // them for deletion.
   for (auto& keyframe_model : keyframe_models()) {
     KeyframeModel* cc_keyframe_model =
         KeyframeModel::ToCcKeyframeModel(keyframe_model.get());
     if (cc_keyframe_model->run_state() == gfx::KeyframeModel::ABORTED) {
-      GenerateEvent(events, *cc_keyframe_model, AnimationEvent::Type::kAborted,
-                    monotonic_time);
+      GenerateEvent(events, *cc_keyframe_model,
+                    AnimationPlaybackEvent::Type::kAborted, monotonic_time);
       // If this is the controlling instance or it has already received finish
       // event, keyframe model can be marked for deletion.
       if (!NeedsFinishedEvent(cc_keyframe_model))
@@ -1061,7 +1061,7 @@
         continue;
 
       GenerateEvent(events, *same_group_keyframe_model,
-                    AnimationEvent::Type::kFinished, monotonic_time);
+                    AnimationPlaybackEvent::Type::kFinished, monotonic_time);
       MarkForDeletion(same_group_keyframe_model);
     }
   }
@@ -1116,7 +1116,7 @@
 
 void KeyframeEffect::GenerateEvent(AnimationEvents* events,
                                    const KeyframeModel& keyframe_model,
-                                   AnimationEvent::Type type,
+                                   AnimationPlaybackEvent::Type type,
                                    base::TimeTicks monotonic_time) {
   // An ungrouped model has been replaced by another model so avoid dispatching
   // any events from it.
@@ -1130,22 +1130,23 @@
 
   if (is_impl_only) {
     // For impl-only animations, create and dispatch the event directly.
-    AnimationEvent event(type,
-                         {animation_->animation_timeline()->id(),
-                          animation_->id(), keyframe_model.id()},
-                         keyframe_model.group(),
-                         keyframe_model.TargetProperty(), monotonic_time);
+    AnimationPlaybackEvent event(type,
+                                 {animation_->animation_timeline()->id(),
+                                  animation_->id(), keyframe_model.id()},
+                                 keyframe_model.group(),
+                                 keyframe_model.TargetProperty(),
+                                 monotonic_time);
     event.is_impl_only = true;
     animation_->DispatchAndDelegateAnimationEvent(event);
   } else {
     // For non-impl-only animations, construct the event directly.
-    events->events().emplace_back(type,
-                                  AnimationEvent::UniqueKeyframeModelId{
-                                      animation_->animation_timeline()->id(),
-                                      animation_->id(), keyframe_model.id()},
-                                  keyframe_model.group(),
-                                  keyframe_model.TargetProperty(),
-                                  monotonic_time);
+    events->events().emplace_back(AnimationPlaybackEvent(
+        type,
+        AnimationPlaybackEvent::UniqueKeyframeModelId{
+            animation_->animation_timeline()->id(), animation_->id(),
+            keyframe_model.id()},
+        keyframe_model.group(), keyframe_model.TargetProperty(),
+        monotonic_time));
   }
 }
 
@@ -1158,15 +1159,16 @@
     return;
 
   // Takeover events are always added to the event list.
-  events->events().emplace_back(
-      AnimationEvent::Type::kTakeOver,
-      AnimationEvent::UniqueKeyframeModelId{
+  events->events().emplace_back(AnimationPlaybackEvent(
+      AnimationPlaybackEvent::Type::kTakeOver,
+      AnimationPlaybackEvent::UniqueKeyframeModelId{
           animation_->animation_timeline()->id(), animation_->id(),
           keyframe_model.id()},
-      keyframe_model.group(), keyframe_model.TargetProperty(), monotonic_time);
+      keyframe_model.group(), keyframe_model.TargetProperty(), monotonic_time));
 
   // Get the event reference just added.
-  auto& takeover_event = events->events().back();
+  auto& takeover_event =
+      std::get<AnimationPlaybackEvent>(events->events().back());
   takeover_event.animation_start_time = keyframe_model.start_time();
   const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
       ScrollOffsetAnimationCurve::ToScrollOffsetAnimationCurve(
@@ -1174,8 +1176,8 @@
   takeover_event.curve = scroll_offset_animation_curve->Clone();
 
   // Create and dispatch the finished event.
-  AnimationEvent finished_event(
-      AnimationEvent::Type::kFinished,
+  AnimationPlaybackEvent finished_event(
+      AnimationPlaybackEvent::Type::kFinished,
       {animation_->animation_timeline()->id(), animation_->id(),
        keyframe_model.id()},
       keyframe_model.group(), keyframe_model.TargetProperty(), monotonic_time);
diff --git a/cc/animation/keyframe_effect.h b/cc/animation/keyframe_effect.h
index e653464..1f5093a 100644
--- a/cc/animation/keyframe_effect.h
+++ b/cc/animation/keyframe_effect.h
@@ -115,7 +115,8 @@
 
   // Dispatches animation event to a keyframe model specified as part of the
   // event. Returns true if the event is dispatched, false otherwise.
-  bool DispatchAnimationEventToKeyframeModel(const AnimationEvent& event);
+  bool DispatchAnimationEventToKeyframeModel(
+      const AnimationPlaybackEvent& event);
 
   // Returns true if there are any KeyframeModels that have neither finished
   // nor aborted.
@@ -190,7 +191,7 @@
   std::optional<gfx::PointF> ScrollOffsetForAnimation() const;
   void GenerateEvent(AnimationEvents* events,
                      const KeyframeModel& keyframe_model,
-                     AnimationEvent::Type type,
+                     AnimationPlaybackEvent::Type type,
                      base::TimeTicks monotonic_time);
   void GenerateTakeoverEventForScrollAnimation(
       AnimationEvents* events,
diff --git a/cc/animation/scroll_timeline.h b/cc/animation/scroll_timeline.h
index bca729cd..afb6f71b 100644
--- a/cc/animation/scroll_timeline.h
+++ b/cc/animation/scroll_timeline.h
@@ -146,10 +146,6 @@
   bool IsScrollTimeline() const override;
   bool IsLinkedToScroller(ElementId scroller) const override;
 
- protected:
-  ~ScrollTimeline() override;
-
- private:
   const std::optional<ElementId>& active_id() const {
     return active_id_.Read(*this);
   }
@@ -158,8 +154,6 @@
     return pending_id_.Read(*this);
   }
 
-  const ScrollDirection& direction() const { return direction_.Read(*this); }
-
   const std::optional<ScrollOffsets>& active_offsets() const {
     return active_offsets_.Read(*this);
   }
@@ -168,6 +162,12 @@
     return pending_offsets_.Read(*this);
   }
 
+ protected:
+  ~ScrollTimeline() override;
+
+ private:
+  const ScrollDirection& direction() const { return direction_.Read(*this); }
+
   // The scroller which this ScrollTimeline is based on. The same underlying
   // scroll source may have different ids in the pending and active tree (see
   // http://crbug.com/847588).
diff --git a/cc/animation/timeline_trigger.cc b/cc/animation/timeline_trigger.cc
index 40a40e6d..ead5bd0 100644
--- a/cc/animation/timeline_trigger.cc
+++ b/cc/animation/timeline_trigger.cc
@@ -12,15 +12,17 @@
 namespace cc {
 
 TimelineTrigger::TimelineTrigger(int id,
-                                 scoped_refptr<AnimationTimeline> timeline)
-    : AnimationTrigger(id), timeline_(timeline) {}
+                                 scoped_refptr<AnimationTimeline> timeline,
+                                 Boundaries boundaries)
+    : AnimationTrigger(id), timeline_(timeline), boundaries_(boundaries) {}
 
 TimelineTrigger::~TimelineTrigger() = default;
 
 scoped_refptr<TimelineTrigger> TimelineTrigger::Create(
     int id,
-    scoped_refptr<AnimationTimeline> timeline) {
-  return base::WrapRefCounted(new TimelineTrigger(id, timeline));
+    scoped_refptr<AnimationTimeline> timeline,
+    Boundaries boundaries) {
+  return base::WrapRefCounted(new TimelineTrigger(id, timeline, boundaries));
 }
 
 scoped_refptr<AnimationTrigger> TimelineTrigger::CreateImplInstance(
@@ -29,7 +31,7 @@
       host_impl.GetScopedRefTimelineById(timeline_.Read(*this)->id());
   CHECK(timeline_impl);
   scoped_refptr<TimelineTrigger> impl_instance =
-      TimelineTrigger::Create(id(), timeline_impl);
+      TimelineTrigger::Create(id(), timeline_impl, boundaries_);
   return impl_instance;
 }
 
@@ -37,4 +39,65 @@
   return true;
 }
 
+bool TimelineTrigger::InActivationRange(base::TimeTicks time) {
+  return boundaries_.activation_start_time <= time &&
+         time <= boundaries_.activation_end_time;
+}
+
+bool TimelineTrigger::InActiveRange(base::TimeTicks time) {
+  return boundaries_.active_start_time <= time &&
+         time <= boundaries_.active_end_time;
+}
+
+AnimationTrigger::State TimelineTrigger::ComputeState(base::TimeTicks time) {
+  if (InActivationRange(time)) {
+    return State::kPrimary;
+  } else if (!InActiveRange(time)) {
+    return State::kInverse;
+  }
+  return state_;
+}
+
+void TimelineTrigger::Update(const ScrollTree& scroll_tree,
+                             AnimationEvents* events) {
+  ScrollTimeline* scroll_timeline =
+      reinterpret_cast<ScrollTimeline*>(timeline_.Read(*this).get());
+  DCHECK(scroll_timeline);
+
+  // Triggers only function based on the active tree.
+  if (!scroll_timeline->IsActive(scroll_tree, /*is_active_tree=*/true)) {
+    return;
+  }
+
+  std::optional<base::TimeTicks> current_time =
+      scroll_timeline->CurrentTime(scroll_tree, /*is_active_tree=*/true);
+  DCHECK(current_time);
+
+  State previous_state = state_;
+  State current_state = ComputeState(*current_time);
+
+  if (previous_state == current_state) {
+    // No state change, no work to do.
+    return;
+  }
+
+  if (previous_state == State::kIdle && current_state == State::kInverse) {
+    // "activate" must be encountered before "deactivate".
+    return;
+  }
+
+  state_ = current_state;
+
+  switch (state_) {
+    case State::kPrimary:
+      PerformActivate(events);
+      break;
+    case State::kInverse:
+      PerformDeactivate(events);
+      break;
+    default:
+      NOTREACHED();
+  }
+}
+
 }  // namespace cc
diff --git a/cc/animation/timeline_trigger.h b/cc/animation/timeline_trigger.h
index 281426f..80e6fced 100644
--- a/cc/animation/timeline_trigger.h
+++ b/cc/animation/timeline_trigger.h
@@ -10,26 +10,57 @@
 namespace cc {
 
 class AnimationTimeline;
+class ScrollTree;
 
 class CC_ANIMATION_EXPORT TimelineTrigger : public AnimationTrigger {
  public:
+  using State = AnimationTrigger::State;
+
+  // Structure to hold the boundaries of the trigger, in units of time -
+  // the units of the timeline's CurrentTime.
+  struct Boundaries {
+    // These denote the start and end of the activation range
+    base::TimeTicks activation_start_time;
+    base::TimeTicks activation_end_time;
+    // These denote the start and end of the active range.
+    base::TimeTicks active_start_time;
+    base::TimeTicks active_end_time;
+  };
+
   static scoped_refptr<TimelineTrigger> Create(
       int id,
-      scoped_refptr<AnimationTimeline> timeline);
+      scoped_refptr<AnimationTimeline> timeline,
+      Boundaries Boundaries);
 
   scoped_refptr<AnimationTrigger> CreateImplInstance(
       AnimationHost& host_impl) const override;
 
   bool IsTimelineTrigger() const override;
 
+  // Update the state of the trigger based on the current time of the timeline,
+  // queueing up trigger events and triggering animations if necessary.
+  void Update(const ScrollTree& scroll_tree, AnimationEvents* events);
+
  protected:
-  explicit TimelineTrigger(int id, scoped_refptr<AnimationTimeline> timeline);
+  explicit TimelineTrigger(int id,
+                           scoped_refptr<AnimationTimeline> timeline,
+                           Boundaries boundaries);
   ~TimelineTrigger() override;
 
  private:
   friend class RefCounted<TimelineTrigger>;
 
+  State ComputeState(base::TimeTicks time);
+  bool InActivationRange(base::TimeTicks time);
+  bool InActiveRange(base::TimeTicks time);
+
   ProtectedSequenceReadable<scoped_refptr<AnimationTimeline>> timeline_;
+
+  // The boundaries of the associated timeline that define the enter and exit
+  // ranges.
+  Boundaries boundaries_;
+  // The most recently observed state of the trigger.
+  State state_ = State::kIdle;
 };
 
 }  // namespace cc
diff --git a/cc/animation/worklet_animation.cc b/cc/animation/worklet_animation.cc
index 31e65ee3..c4c8c7e5 100644
--- a/cc/animation/worklet_animation.cc
+++ b/cc/animation/worklet_animation.cc
@@ -86,8 +86,8 @@
 void WorkletAnimation::TakeTimeUpdatedEvent(AnimationEvents* events) {
   DCHECK(events->needs_time_updated_events());
   if (last_synced_local_time_.Read(*this) != local_time_.Read(*this)) {
-    events->events().emplace_back(animation_timeline()->id(), id_,
-                                  local_time_.Read(*this));
+    events->events().emplace_back(AnimationPlaybackEvent(
+        animation_timeline()->id(), id_, local_time_.Read(*this)));
     last_synced_local_time_.Write(*this) = local_time_.Read(*this);
   }
 }
diff --git a/cc/animation/worklet_animation_unittest.cc b/cc/animation/worklet_animation_unittest.cc
index 8221fcd..b8e5d60 100644
--- a/cc/animation/worklet_animation_unittest.cc
+++ b/cc/animation/worklet_animation_unittest.cc
@@ -118,7 +118,7 @@
 }
 
 // Test generation of animation events by worklet animations.
-TEST_F(WorkletAnimationTest, AnimationEventLocalTimeUpdate) {
+TEST_F(WorkletAnimationTest, AnimationPlaybackEventLocalTimeUpdate) {
   AttachWorkletAnimation();
 
   std::optional<base::TimeDelta> local_time = base::Seconds(1);
@@ -134,10 +134,11 @@
   EXPECT_TRUE(animation_events->needs_time_updated_events());
   worklet_animation_->TakeTimeUpdatedEvent(animation_events);
   EXPECT_EQ(1u, animation_events->events().size());
-  AnimationEvent event = animation_events->events()[0];
-  EXPECT_EQ(AnimationEvent::Type::kTimeUpdated, event.type);
-  EXPECT_EQ(worklet_animation_->id(), event.uid.animation_id);
-  EXPECT_EQ(local_time, event.local_time);
+  const auto* event =
+      std::get_if<AnimationPlaybackEvent>(&animation_events->events()[0]);
+  EXPECT_EQ(AnimationPlaybackEvent::Type::kTimeUpdated, event->type);
+  EXPECT_EQ(worklet_animation_->id(), event->uid.animation_id);
+  EXPECT_EQ(local_time, event->local_time);
 
   // If the state is not updated no more events is generated.
   mutator_events = host_->CreateEvents();
@@ -164,7 +165,8 @@
   EXPECT_TRUE(animation_events->needs_time_updated_events());
   worklet_animation_->TakeTimeUpdatedEvent(animation_events);
   EXPECT_EQ(1u, animation_events->events().size());
-  EXPECT_EQ(local_time, animation_events->events()[0].local_time);
+  event = std::get_if<AnimationPlaybackEvent>(&animation_events->events()[0]);
+  EXPECT_EQ(local_time, event->local_time);
 }
 
 TEST_F(WorkletAnimationTest, CurrentTimeCorrectlyUsesScrollTimeline) {
diff --git a/cc/test/animation_timelines_test_common.cc b/cc/test/animation_timelines_test_common.cc
index 2ff456a8..6c418593 100644
--- a/cc/test/animation_timelines_test_common.cc
+++ b/cc/test/animation_timelines_test_common.cc
@@ -512,13 +512,13 @@
 
   // TODO(smcgruer): Construct a proper ScrollTree for the tests.
   ScrollTree scroll_tree;
-  host_impl_->TickAnimations(time, scroll_tree, true);
+  host_impl_->TickAnimations(time, scroll_tree, true, events.get());
   host_impl_->UpdateAnimationState(true, events.get());
 
   auto* animation_events = static_cast<const AnimationEvents*>(events.get());
   EXPECT_EQ(expect_events, animation_events->events().size());
 
-  host_->TickAnimations(time, scroll_tree, true);
+  host_->TickAnimations(time, scroll_tree, true, nullptr);
   host_->UpdateAnimationState(true, nullptr);
   host_->SetAnimationEvents(std::move(events));
 }
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc
index 2625bbc6..0d8b5c2 100644
--- a/cc/tiles/gpu_image_decode_cache.cc
+++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -10,7 +10,6 @@
 #include <limits>
 #include <string>
 
-#include "base/auto_reset.h"
 #include "base/command_line.h"
 #include "base/containers/span.h"
 #include "base/debug/alias.h"
@@ -996,10 +995,6 @@
         this, "cc::GpuImageDecodeCache",
         base::SingleThreadTaskRunner::GetCurrentDefault());
   }
-  memory_pressure_listener_registration_ =
-      std::make_unique<base::AsyncMemoryPressureListenerRegistration>(
-          FROM_HERE, base::MemoryPressureListenerTag::kGpuImageDecodeCache,
-          this);
 
   TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                "GpuImageDecodeCache::DarkModeFilter", "dark_mode_filter",
@@ -2695,15 +2690,6 @@
   image_data->last_use = base::TimeTicks::Now();
 }
 
-void GpuImageDecodeCache::OnMemoryPressure(base::MemoryPressureLevel level) {
-  if (!ImageDecodeCacheUtils::ShouldEvictCaches(level))
-    return;
-
-  base::AutoLock lock(lock_);
-  base::AutoReset<bool> reset(&aggressively_freeing_resources_, true);
-  ReduceCacheUsageLocked();
-}
-
 bool GpuImageDecodeCache::AcquireContextLockForTesting() {
   if (!context_->GetLock()) {
     return false;
diff --git a/cc/tiles/gpu_image_decode_cache.h b/cc/tiles/gpu_image_decode_cache.h
index 05b62127..3a22fdeb 100644
--- a/cc/tiles/gpu_image_decode_cache.h
+++ b/cc/tiles/gpu_image_decode_cache.h
@@ -19,7 +19,6 @@
 #include "base/containers/lru_cache.h"
 #include "base/logging.h"
 #include "base/memory/discardable_memory.h"
-#include "base/memory/memory_pressure_listener.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/raw_ptr_exclusion.h"
 #include "base/memory/ref_counted.h"
@@ -112,8 +111,7 @@
 //      |persistent_cache_| or |in_use_cache_|.
 class CC_EXPORT GpuImageDecodeCache
     : public ImageDecodeCache,
-      public base::trace_event::MemoryDumpProvider,
-      public base::MemoryPressureListener {
+      public base::trace_event::MemoryDumpProvider {
  public:
   explicit GpuImageDecodeCache(viz::RasterContextProvider* context,
                                SkColorType color_type,
@@ -153,10 +151,6 @@
   bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                     base::trace_event::ProcessMemoryDump* pmd) override;
 
-  // TODO(gyuyoung): OnMemoryPressure is deprecated. So this should be removed
-  // when the memory coordinator is enabled by default.
-  void OnMemoryPressure(base::MemoryPressureLevel level) override;
-
   // Called by Decode / Upload tasks.
   void DecodeImageInTask(const DrawImage& image, TaskType task_type);
   void UploadImageInTask(const DrawImage& image);
@@ -721,8 +715,6 @@
   std::vector<uint32_t> ids_pending_unlock_;
   std::vector<uint32_t> ids_pending_deletion_;
 
-  std::unique_ptr<base::AsyncMemoryPressureListenerRegistration>
-      memory_pressure_listener_registration_;
   base::WeakPtrFactory<GpuImageDecodeCache> weak_ptr_factory_{this};
 };
 
diff --git a/cc/tiles/gpu_image_decode_cache_unittest.cc b/cc/tiles/gpu_image_decode_cache_unittest.cc
index 6d8460c..ee5c678 100644
--- a/cc/tiles/gpu_image_decode_cache_unittest.cc
+++ b/cc/tiles/gpu_image_decode_cache_unittest.cc
@@ -2988,10 +2988,8 @@
     cache->DrawWithImageFinished(draw_images[i], decoded_draw_images[i]);
   }
 
-  // We have a single tracked entry, that gets cleared once we purge the cache.
+  // We have a single tracked entry.
   EXPECT_EQ(cache->paint_image_entries_count_for_testing(), 1u);
-  cache->OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_CRITICAL);
-  EXPECT_EQ(cache->paint_image_entries_count_for_testing(), 0u);
 }
 
 TEST_P(GpuImageDecodeCacheTest, DecodeToScale) {
diff --git a/cc/tiles/image_decode_cache_utils.cc b/cc/tiles/image_decode_cache_utils.cc
index 4d9c118..12abb1c9 100644
--- a/cc/tiles/image_decode_cache_utils.cc
+++ b/cc/tiles/image_decode_cache_utils.cc
@@ -8,12 +8,7 @@
 #include "cc/tiles/image_decode_cache_utils.h"
 
 #include "base/byte_count.h"
-#include "base/check.h"
-#include "base/notreached.h"
-#include "cc/paint/paint_flags.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkImageInfo.h"
-#include "third_party/skia/include/core/SkPixmap.h"
+#include "build/build_config.h"
 
 #if !BUILDFLAG(IS_ANDROID)
 #include "base/system/sys_info.h"
@@ -22,19 +17,6 @@
 namespace cc {
 
 // static
-bool ImageDecodeCacheUtils::ShouldEvictCaches(
-    base::MemoryPressureLevel memory_pressure_level) {
-  switch (memory_pressure_level) {
-    case base::MEMORY_PRESSURE_LEVEL_NONE:
-    case base::MEMORY_PRESSURE_LEVEL_MODERATE:
-      return false;
-    case base::MEMORY_PRESSURE_LEVEL_CRITICAL:
-      return true;
-  }
-  NOTREACHED();
-}
-
-// static
 size_t ImageDecodeCacheUtils::GetWorkingSetBytesForImageDecode(
     bool for_renderer) {
   base::ByteCount decoded_image_working_set_budget = base::MiB(128);
diff --git a/cc/tiles/image_decode_cache_utils.h b/cc/tiles/image_decode_cache_utils.h
index 3bfc21c..79df7757 100644
--- a/cc/tiles/image_decode_cache_utils.h
+++ b/cc/tiles/image_decode_cache_utils.h
@@ -7,16 +7,12 @@
 
 #include <stddef.h>
 
-#include "base/memory/memory_pressure_level.h"
 #include "cc/cc_export.h"
 
 namespace cc {
 
 class CC_EXPORT ImageDecodeCacheUtils {
  public:
-  static bool ShouldEvictCaches(
-      base::MemoryPressureLevel memory_pressure_level);
-
   // Returns budget bytes for decoded images that may be different depending
   // whether it's for renderer or for the ui compositor.
   static size_t GetWorkingSetBytesForImageDecode(bool for_renderer);
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 22b3d56..5a2d613 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -1264,8 +1264,10 @@
   std::unique_ptr<MutatorEvents> events = mutator_host()->CreateEvents();
 
   if (mutator_host()->TickAnimations(monotonic_time,
-                                     property_trees()->scroll_tree(), true))
+                                     property_trees()->scroll_tree(), true,
+                                     events.get())) {
     mutator_host()->UpdateAnimationState(true, events.get());
+  }
 
   if (!events->IsEmpty()) {
     property_tree_delegate_->OnAnimateLayers();
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 0f810632..ccc7295 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -5423,7 +5423,7 @@
       is_active_tree ? active_tree_->property_trees()->scroll_tree()
                      : pending_tree_->property_trees()->scroll_tree();
   const bool animated = mutator_host_->TickAnimations(
-      monotonic_time, scroll_tree, is_active_tree);
+      monotonic_time, scroll_tree, is_active_tree, mutator_events_.get());
 
   // TODO(crbug.com/40443202): Only do this if the animations are on the active
   // tree, or if they are on the pending tree waiting for some future time to
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index c23f217..46e0e35 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -18540,7 +18540,7 @@
 
   // Bring the animations to their initial values (current_offset).
   animation_host->TickAnimations(base::TimeTicks() + base::Milliseconds(200),
-                                 host_impl_->GetScrollTree(), true);
+                                 host_impl_->GetScrollTree(), true, nullptr);
   EXPECT_EQ(host_impl_->GetScrollTree().current_scroll_offset(
                 scroller1_->element_id()),
             current_offset1_);
@@ -18553,7 +18553,7 @@
 
   // Bring the animations to intermediate values.
   animation_host->TickAnimations(base::TimeTicks() + base::Milliseconds(300),
-                                 host_impl_->GetScrollTree(), true);
+                                 host_impl_->GetScrollTree(), true, nullptr);
   EXPECT_GT(host_impl_->GetScrollTree()
                 .current_scroll_offset(scroller1_->element_id())
                 .y(),
@@ -18570,7 +18570,7 @@
   AnimationHost* animation_host = GetImplAnimationHost();
   // Bring the animations to their final values.
   animation_host->TickAnimations(base::TimeTicks() + base::Milliseconds(600),
-                                 host_impl_->GetScrollTree(), true);
+                                 host_impl_->GetScrollTree(), true, nullptr);
   // Bring the animations to a FINISHED state.
   animation_host->UpdateAnimationState(true, nullptr);
 
@@ -18760,7 +18760,7 @@
   while (animation_host->HasImplOnlyScrollAnimatingElement()) {
     animation_host->TickAnimations(
         base::TimeTicks() + base::Milliseconds(t++ * 100),
-        host_impl_->GetScrollTree(), true);
+        host_impl_->GetScrollTree(), true, nullptr);
     animation_host->UpdateAnimationState(true, nullptr);
   }
 
diff --git a/cc/trees/mutator_host.h b/cc/trees/mutator_host.h
index 64c131b..6b44f3d 100644
--- a/cc/trees/mutator_host.h
+++ b/cc/trees/mutator_host.h
@@ -69,7 +69,8 @@
   // don't need to pass the scroll tree in here.
   virtual bool TickAnimations(base::TimeTicks monotonic_time,
                               const ScrollTree& scroll_tree,
-                              bool is_active_tree) = 0;
+                              bool is_active_tree,
+                              MutatorEvents* events) = 0;
   // Tick animations that depends on scroll offset.
   virtual void TickScrollAnimations(base::TimeTicks monotonic_time,
                                     const ScrollTree& scroll_tree) = 0;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index f05ca15a..66be0e4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -365,6 +365,7 @@
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.common.ContentSwitches;
+import org.chromium.ui.base.AcceleratorManager;
 import org.chromium.ui.base.DeviceFormFactor;
 import org.chromium.ui.base.PageTransition;
 import org.chromium.ui.base.WindowAndroid;
@@ -605,6 +606,7 @@
     private Runnable mShowHistoryRunnable;
     private CompositorViewHolder mCompositorViewHolder;
     private IncognitoWindowNightModeStateProvider mIncognitoWindowNightModeStateProvider;
+    private AcceleratorManager mAcceleratorManager;
 
     /** Keeps track of whether or not a specific tab was created based on the startup intent. */
     private boolean mCreatedTabOnStartup;
@@ -3010,6 +3012,7 @@
     @Override
     public void performPreInflationStartup() {
         super.performPreInflationStartup();
+        mAcceleratorManager = AcceleratorManager.getOrCreate(getWindowAndroid());
 
         if (isMainIntentLaunchPreOnResume()) {
             StartupLatencyInjector startupLatencyInjector = new StartupLatencyInjector();
@@ -4729,6 +4732,10 @@
                     .destroy(mRecentlyClosedEntriesManager);
         }
 
+        if (mAcceleratorManager != null) {
+            mAcceleratorManager.destroy();
+        }
+
         super.onDestroyInternal();
     }
 
@@ -4768,6 +4775,10 @@
             }
         }
 
+        if (mAcceleratorManager.processKeyEvent(event)) {
+            result = true;
+        }
+
         return result != null ? result : super.dispatchKeyEvent(event);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java
index e816899c..cf0dc74 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java
@@ -1716,21 +1716,13 @@
     @Nullable
     @BrowserWindowType
     Integer getSupportedBrowserWindowType() {
-        // PWA
-        if (mIntentDataProvider.getActivityType() == ActivityType.WEBAPP) {
-            return BrowserWindowType.APP;
-        }
+        // TODO (crbug.com/486858979): Temporarily removed TWA and PWA support to avoid crashes.
 
         @CustomTabsUiType int type = mIntentDataProvider.getUiType();
         switch (type) {
             // Popups
             case CustomTabsUiType.POPUP:
                 return BrowserWindowType.POPUP;
-            // PWA and TWA
-            case CustomTabsUiType.MINIMAL_UI_WEBAPP:
-            /* fallthrough */
-            case CustomTabsUiType.TRUSTED_WEB_ACTIVITY:
-                return BrowserWindowType.APP;
             default:
                 break;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java
index dc65dbcb..c80cb1b1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java
@@ -1124,11 +1124,22 @@
         // notification is tapped while the target activity is backgrounded (minimized).
         AppTask appTask = AndroidTaskUtils.getAppTaskFromId(activity, taskId);
         if (appTask != null) {
-            // Remove NEW_TASK to prevent the OS from spawning a duplicate instance,
-            // and strictly target the existing activity class.
-            intent.removeFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             intent.setClass(ContextUtils.getApplicationContext(), activity.getClass());
-            appTask.startActivity(ContextUtils.getApplicationContext(), intent, null);
+            if (MultiWindowUtils.isMultiInstanceApi31Enabled()) {
+                // Remove NEW_TASK to prevent the OS from spawning a duplicate instance,
+                // and strictly target the existing activity class.
+                intent.removeFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                appTask.startActivity(ContextUtils.getApplicationContext(), intent, null);
+            } else {
+                // On older Android versions or devices where multi-instance is not enabled, the OS
+                // enforces strict singleTask checks on AppTask.startActivity() and throws an
+                // exception if the task is not empty. However, since these versions do not support
+                // multiple tasks for the same ChromeTabbedActivity class, we can safely fallback
+                // to Context.startActivity() with NEW_TASK, which will inherently route to the
+                // correct task and still bypass BAL restrictions.
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                IntentUtils.safeStartActivity(ContextUtils.getApplicationContext(), intent);
+            }
             return true;
         }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/MultiWindowAppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/MultiWindowAppMenuTest.java
index 4c2ea99..2971c16 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/MultiWindowAppMenuTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/MultiWindowAppMenuTest.java
@@ -12,7 +12,7 @@
 
 import org.chromium.base.test.transit.TransitAsserts;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.DisabledTest;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DoNotBatch;
 import org.chromium.base.test.util.Features.DisableFeatures;
 import org.chromium.base.test.util.Features.EnableFeatures;
@@ -70,7 +70,7 @@
     @Test
     @LargeTest
     @EnableFeatures(OPEN_WINDOW_ON_TOP)
-    @DisabledTest(message = "https://crbug.com/485606369")
+    @DisableIf.Device(DeviceFormFactor.DESKTOP_FREEFORM) // https://crbug.com/485606369
     public void testOpenNewWindow_fromIncognitoNtp_robustWindowManagementExperimentalEnabled() {
         doTestOpenNewWindow_fromIncognitoNtp();
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java
index de5b7595..394fbbe7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java
@@ -19,7 +19,6 @@
 import static org.chromium.base.test.transit.ViewFinder.waitForNoView;
 import static org.chromium.chrome.browser.url_constants.UrlConstantResolver.getOriginalNativeNtpUrl;
 
-import android.content.Intent;
 import android.content.res.Configuration;
 import android.view.View;
 import android.view.ViewGroup;
@@ -30,7 +29,6 @@
 import androidx.test.filters.MediumTest;
 import androidx.test.filters.SmallTest;
 
-import org.hamcrest.Matchers;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -42,10 +40,8 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
-import org.chromium.base.CommandLine;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.DoNotBatch;
 import org.chromium.base.test.util.Features.DisableFeatures;
@@ -56,7 +52,6 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.lens.LensController;
-import org.chromium.chrome.browser.lifecycle.InflationObserver;
 import org.chromium.chrome.browser.locale.LocaleManager;
 import org.chromium.chrome.browser.locale.LocaleManagerDelegate;
 import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler;
@@ -82,7 +77,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /** Instrumentation tests for the LocationBar component. */
 @RunWith(ChromeJUnit4ClassRunner.class)
@@ -141,41 +135,6 @@
         return webPageStation;
     }
 
-    private void startActivityWithDeferredNativeInitialization() {
-        CommandLine.getInstance().appendSwitch(ChromeSwitches.DISABLE_NATIVE_INITIALIZATION);
-        Intent intent = new Intent("about:blank");
-        intent.addCategory(Intent.CATEGORY_LAUNCHER);
-        mActivityTestRule.getActivityTestRule().prepareUrlIntent(intent, "about:blank");
-        mActivityTestRule.getActivityTestRule().launchActivity(intent);
-        mActivity = mActivityTestRule.getActivity();
-        if (!mActivity.isInitialLayoutInflationComplete()) {
-            AtomicBoolean isInflated = new AtomicBoolean();
-            mActivity
-                    .getLifecycleDispatcher()
-                    .register(
-                            new InflationObserver() {
-                                @Override
-                                public void onPreInflationStartup() {}
-
-                                @Override
-                                public void onPostInflationStartup() {
-                                    isInflated.set(true);
-                                }
-                            });
-            CriteriaHelper.pollUiThread(isInflated::get);
-        }
-        doPostActivitySetup(mActivity);
-    }
-
-    private void triggerAndWaitForDeferredNativeInitialization() {
-        CommandLine.getInstance().removeSwitch(ChromeSwitches.DISABLE_NATIVE_INITIALIZATION);
-        ThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    mActivityTestRule.getActivity().startDelayedNativeInitializationForTests();
-                });
-        mActivityTestRule.waitForActivityNativeInitializationComplete();
-    }
-
     private void doPostActivitySetup(ChromeActivity activity) {
         mOmnibox = new OmniboxTestUtils(activity);
         mUrlBar = activity.findViewById(R.id.url_bar);
@@ -285,27 +244,6 @@
 
     @Test
     @MediumTest
-    public void testSetSearchQueryFocusesUrlBar_preNative() {
-        startActivityWithDeferredNativeInitialization();
-        final String query = "testing query";
-        ThreadUtils.runOnUiThreadBlocking(
-                () -> {
-                    AutocompleteInput input =
-                            new AutocompleteInput()
-                                    .setUserText(query)
-                                    .setFocusReason(OmniboxFocusReason.SEARCH_QUERY);
-                    mLocationBarMediator.beginInput(input);
-                });
-        triggerAndWaitForDeferredNativeInitialization();
-        CriteriaHelper.pollUiThread(
-                () -> {
-                    Criteria.checkThat(mUrlBar.getTextWithoutAutocomplete(), Matchers.is(query));
-                    Criteria.checkThat(mLocationBarMediator.isUrlBarFocused(), Matchers.is(true));
-                });
-    }
-
-    @Test
-    @MediumTest
     public void testOnConfigurationChanged() {
         startActivityNormally();
         // We expect the UrlBar to be focused iff a Hardware keyboard handler does not automatically
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 2e3be04..06b0b4d 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -19455,6 +19455,9 @@
       <message name="IDS_GLIC_SHARE_IMAGE_FAILED_TOAST_BODY" desc="Text on a toast notification that is shown when sharing an image with Gemini fails (when using the 'Create image with Gemini' context menu item)">
         Could not share image with Gemini. Try again or try another image.
       </message>
+      <message name="IDS_GLIC_SELECTION_OVERLAY_RENDERER_LABEL" desc="The label for the renderer process housing the Gemini's selection overlay.">
+        Gemini Selection Overlay
+      </message>
       <message name="IDS_COPIED_TO_CLIPBOARD_TOAST_BODY" desc="Text on a toast notification that is shown when an item has been copied to clipboard.">
         Copied to clipboard
       </message>
diff --git a/chrome/app/generated_resources_grd/IDS_GLIC_SELECTION_OVERLAY_RENDERER_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_GLIC_SELECTION_OVERLAY_RENDERER_LABEL.png.sha1
new file mode 100644
index 0000000..6184843
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_GLIC_SELECTION_OVERLAY_RENDERER_LABEL.png.sha1
@@ -0,0 +1 @@
+84acae19d6e35f75da13c20e39e396f4f30808ca
\ No newline at end of file
diff --git a/chrome/app/glic_strings.grdp b/chrome/app/glic_strings.grdp
index 73cf7710..c8ee43dc1 100644
--- a/chrome/app/glic_strings.grdp
+++ b/chrome/app/glic_strings.grdp
@@ -144,6 +144,9 @@
   <message name="IDS_SETTINGS_GLIC_KEYBOARD_SHORTCUT_EDIT_LABEL" desc="Label of the edit keyboard shortcut setting button.">
     Edit keyboard shortcut
   </message>
+  <message name="IDS_SETTINGS_GLIC_KEYBOARD_SHORTCUT_CLEAR_LABEL" desc="Label of the clear keyboard shortcut setting button.">
+    Clear keyboard shortcut
+  </message>
   <message name="IDS_SETTINGS_GLIC_KEYBOARD_SHORTCUT_SUBLABEL" desc="Sublabel describing the keyboard shortcut that's used to globally invoke Gemini.">
     Open Gemini with a keyboard shortcut.
   </message>
@@ -162,6 +165,9 @@
   <message name="IDS_SETTINGS_GLIC_NAVIGATION_SHORTCUT_EDIT_LABEL" desc="Label of the edit navigation shortcut setting button.">
     Edit navigation shortcut
   </message>
+  <message name="IDS_SETTINGS_GLIC_NAVIGATION_SHORTCUT_CLEAR_LABEL" desc="Label of the clear navigation shortcut setting button.">
+    Clear navigation shortcut
+  </message>
   <message name="IDS_SETTINGS_GLIC_NAVIGATION_SHORTCUT_SUBLABEL" desc="Sublabel describing the keyboard shortcut navigate between Chrome and Gemini.">
     To leave or return to Gemini, use keyboard shortcut.
   </message>
diff --git a/chrome/app/glic_strings_grdp/IDS_SETTINGS_GLIC_KEYBOARD_SHORTCUT_CLEAR_LABEL.png.sha1 b/chrome/app/glic_strings_grdp/IDS_SETTINGS_GLIC_KEYBOARD_SHORTCUT_CLEAR_LABEL.png.sha1
new file mode 100644
index 0000000..bb4ceb2
--- /dev/null
+++ b/chrome/app/glic_strings_grdp/IDS_SETTINGS_GLIC_KEYBOARD_SHORTCUT_CLEAR_LABEL.png.sha1
@@ -0,0 +1 @@
+9736ed707d24206b8d94d9065e1dd40d80c53ca2
\ No newline at end of file
diff --git a/chrome/app/glic_strings_grdp/IDS_SETTINGS_GLIC_NAVIGATION_SHORTCUT_CLEAR_LABEL.png.sha1 b/chrome/app/glic_strings_grdp/IDS_SETTINGS_GLIC_NAVIGATION_SHORTCUT_CLEAR_LABEL.png.sha1
new file mode 100644
index 0000000..62416cc
--- /dev/null
+++ b/chrome/app/glic_strings_grdp/IDS_SETTINGS_GLIC_NAVIGATION_SHORTCUT_CLEAR_LABEL.png.sha1
@@ -0,0 +1 @@
+e6a119f49b8984c0d8e80f1c6476c2b2f916298a
\ No newline at end of file
diff --git a/chrome/app/shortcut_input_strings.grdp b/chrome/app/shortcut_input_strings.grdp
index d42d2d7..65ad628 100644
--- a/chrome/app/shortcut_input_strings.grdp
+++ b/chrome/app/shortcut_input_strings.grdp
@@ -36,4 +36,7 @@
   <message name="IDS_SHORTCUT_NEED_CHARACTER" desc="Error message explaining that a shortcut needs a character. This is only shown if a valid modifier is already entered.">
     Type a letter
   </message>
+  <message name="IDS_SHORTCUT_CLEAR" desc="The label for the button to clear the shortcut.">
+    Clear
+  </message>
 </grit-part>
diff --git a/chrome/app/shortcut_input_strings_grdp/IDS_SHORTCUT_CLEAR.png.sha1 b/chrome/app/shortcut_input_strings_grdp/IDS_SHORTCUT_CLEAR.png.sha1
new file mode 100644
index 0000000..62416cc
--- /dev/null
+++ b/chrome/app/shortcut_input_strings_grdp/IDS_SHORTCUT_CLEAR.png.sha1
@@ -0,0 +1 @@
+e6a119f49b8984c0d8e80f1c6476c2b2f916298a
\ No newline at end of file
diff --git a/chrome/app/skills_strings.grdp b/chrome/app/skills_strings.grdp
index fd507ae5..38f1a79 100644
--- a/chrome/app/skills_strings.grdp
+++ b/chrome/app/skills_strings.grdp
@@ -1,21 +1,21 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- Skills specific strings (included from generated_resources.grd). -->
 <grit-part>
-   <message name="IDS_SKILL_SAVED_TOAST_BODY" desc="Text on the toast after a skill is saved" translateable="false">
+   <message name="IDS_SKILL_SAVED_TOAST_BODY" desc="Text on the toast after a skill is saved">
     Saved skill
   </message>
-  <message name="IDS_SKILL_SAVED_TOAST_BUTTON" desc="Text on the toast action button after a skill is saved" translateable="false">
+  <message name="IDS_SKILL_SAVED_TOAST_BUTTON" desc="Text on the toast action button after a skill is saved">
     Try with Gemini in Chrome
   </message>
-  <message name="IDS_SKILL_DELETED_TOAST_BODY" desc="Text on the toast action button after a skill is saved" translateable="false">
+  <message name="IDS_SKILL_DELETED_TOAST_BODY" desc="Text on the toast action button after a skill is saved">
     Deleted skill
   </message>
 
   <!-- a11y strings -->
-  <message name="IDS_SKILL_CARD_ACTION_MENU_LABEL" desc="Accessibility label for button that opens a dropdown on a skill card with options for deleting or copying the text of a skill." translateable="false">
+  <message name="IDS_SKILL_CARD_ACTION_MENU_LABEL" is_accessibility_with_no_ui="true" desc="Accessibility label for button that opens a dropdown on a skill card with options for deleting or copying the text of a skill.">
     Manage your skill
   </message>
-  <message name="IDS_ADD_NEW_SKILL_LABEL" desc="Accessibility label for the add button that opens a dialog allowing users to create a new skill." translateable="false">
+  <message name="IDS_ADD_NEW_SKILL_LABEL" is_accessibility_with_no_ui="true" desc="Accessibility label for the add button that opens a dialog allowing users to create a new skill.">
     Add a new skill
   </message>
 
@@ -122,7 +122,7 @@
     Something went wrong
   </message>
   <message name="IDS_SKILLS_DIALOG_ACCOUNT_INFO" desc="Text for account info in the skills dialog" translateable="false">
-    This skill will save to your Google Account
+    Your skills get saved to your Google Account
   </message>
   <message name="IDS_SKILLS_DIALOG_SAVE_ERROR" desc="Error message for saving a skill" translateable="false">
     Unable to save. Try again
diff --git a/chrome/app/skills_strings_grdp/IDS_SKILL_DELETED_TOAST_BODY.png.sha1 b/chrome/app/skills_strings_grdp/IDS_SKILL_DELETED_TOAST_BODY.png.sha1
new file mode 100644
index 0000000..6e6ca5c
--- /dev/null
+++ b/chrome/app/skills_strings_grdp/IDS_SKILL_DELETED_TOAST_BODY.png.sha1
@@ -0,0 +1 @@
+df26f5f051169b1f625133fdfd8b9267c5bf98e7
\ No newline at end of file
diff --git a/chrome/app/skills_strings_grdp/IDS_SKILL_SAVED_TOAST_BODY.png.sha1 b/chrome/app/skills_strings_grdp/IDS_SKILL_SAVED_TOAST_BODY.png.sha1
new file mode 100644
index 0000000..a814f668
--- /dev/null
+++ b/chrome/app/skills_strings_grdp/IDS_SKILL_SAVED_TOAST_BODY.png.sha1
@@ -0,0 +1 @@
+1a35b5957fcb26e37fdb8abc29febe1646629541
\ No newline at end of file
diff --git a/chrome/app/skills_strings_grdp/IDS_SKILL_SAVED_TOAST_BUTTON.png.sha1 b/chrome/app/skills_strings_grdp/IDS_SKILL_SAVED_TOAST_BUTTON.png.sha1
new file mode 100644
index 0000000..a814f668
--- /dev/null
+++ b/chrome/app/skills_strings_grdp/IDS_SKILL_SAVED_TOAST_BUTTON.png.sha1
@@ -0,0 +1 @@
+1a35b5957fcb26e37fdb8abc29febe1646629541
\ No newline at end of file
diff --git a/chrome/app/skills_strings_grdp/OWNERS b/chrome/app/skills_strings_grdp/OWNERS
new file mode 100644
index 0000000..ec74d7b5
--- /dev/null
+++ b/chrome/app/skills_strings_grdp/OWNERS
@@ -0,0 +1 @@
+file://chrome/browser/skills/OWNERS
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 2318bcd..372aafa 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1021,51 +1021,6 @@
     "policy/webusb_allow_devices_for_urls_policy_handler.h",
     "power_bookmarks/power_bookmark_service_factory.cc",
     "power_bookmarks/power_bookmark_service_factory.h",
-    "predictors/autocomplete_action_predictor.cc",
-    "predictors/autocomplete_action_predictor.h",
-    "predictors/autocomplete_action_predictor_factory.cc",
-    "predictors/autocomplete_action_predictor_factory.h",
-    "predictors/autocomplete_action_predictor_table.cc",
-    "predictors/autocomplete_action_predictor_table.h",
-    "predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_host.cc",
-    "predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_host.h",
-    "predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.cc",
-    "predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h",
-    "predictors/lcp_critical_path_predictor/prewarm_http_disk_cache_manager.cc",
-    "predictors/lcp_critical_path_predictor/prewarm_http_disk_cache_manager.h",
-    "predictors/loading_data_collector.cc",
-    "predictors/loading_data_collector.h",
-    "predictors/loading_predictor.cc",
-    "predictors/loading_predictor.h",
-    "predictors/loading_predictor_config.cc",
-    "predictors/loading_predictor_config.h",
-    "predictors/loading_predictor_factory.cc",
-    "predictors/loading_predictor_factory.h",
-    "predictors/loading_predictor_tab_helper.cc",
-    "predictors/loading_predictor_tab_helper.h",
-    "predictors/loading_stats_collector.cc",
-    "predictors/loading_stats_collector.h",
-    "predictors/network_hints_handler_impl.cc",
-    "predictors/network_hints_handler_impl.h",
-    "predictors/perform_network_context_prefetch.cc",
-    "predictors/perform_network_context_prefetch.h",
-    "predictors/predictor_database.cc",
-    "predictors/predictor_database.h",
-    "predictors/predictor_database_factory.cc",
-    "predictors/predictor_database_factory.h",
-    "predictors/predictors_enums.h",
-    "predictors/predictors_features.cc",
-    "predictors/predictors_features.h",
-    "predictors/predictors_switches.cc",
-    "predictors/predictors_switches.h",
-    "predictors/predictors_traffic_annotations.h",
-    "predictors/prefetch_manager.cc",
-    "predictors/prefetch_manager.h",
-    "predictors/prefetch_traffic_annotation.h",
-    "predictors/resource_prefetch_predictor.cc",
-    "predictors/resource_prefetch_predictor.h",
-    "predictors/resource_prefetch_predictor_tables.cc",
-    "predictors/resource_prefetch_predictor_tables.h",
     "preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline.cc",
     "preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline.h",
     "preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline_manager.cc",
@@ -1572,8 +1527,18 @@
     # - c/b/tab_contents/
     "//chrome/browser/ui/login:impl",
 
-    # TODO(crbug.com/486498788): Remove when c/b/predictors get modularized.
-    "//chrome/browser/preloading/prefetch/no_state_prefetch:impl",
+    # TODO(crbug.com/408146612): Remove this circular dependency when the
+    # following headers get modularized:
+    # - c/b/browser_features.h
+    # - c/b/preloading/prerender/prerender_manager.h
+    # - c/b/preloading/prerender/prerender_utils.h
+    "//chrome/browser/predictors:impl",
+
+    # TODO(crbug.com/487357837): Remove this circular dependency when the
+    # following headers get modularized:
+    # - c/b/after_startup_task_utils.h
+    # - c/b/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer.h
+    "//chrome/browser/predictors/lcp_critical_path_predictor:impl",
 
     # TODO(crbug.com/): This is needed because tab_contents code
     # includes c/b/enterprise/connectors/analysis/content_analysis_delegate.h
@@ -1686,9 +1651,7 @@
     ":flags",
     ":font_pref",
     ":global_features",
-    ":lcp_critical_path_predictor_proto",
     ":main_extra_parts",
-    ":resource_prefetch_predictor_proto",
     ":shell_integration",
     ":unexpire_flags",
     "//base",
@@ -1836,6 +1799,9 @@
     "//chrome/browser/policy:path_parser",
     "//chrome/browser/policy:policy_util",
     "//chrome/browser/policy/messaging_layer/storage_selector",
+    "//chrome/browser/predictors",
+    "//chrome/browser/predictors:impl",
+    "//chrome/browser/predictors/lcp_critical_path_predictor:impl",
     "//chrome/browser/prefetch",
     "//chrome/browser/prefs",
     "//chrome/browser/prefs:impl",
@@ -3584,7 +3550,6 @@
 
       # TODO(crbug.com/353332589): Remove this circular dependency when the following
       # headers get componentized:
-      # - c/b/predictors/predictors_features.h
       # - c/b/browser_features.h
       "//chrome/browser/flags:flags_android_impl",
 
@@ -6181,6 +6146,7 @@
     if (!is_android) {
       deps += [
         "//chrome/browser/glic/media",
+        "//chrome/browser/glic/selection",
         "//chrome/browser/skills",
       ]
       allow_circular_includes_from += [ "//chrome/browser/glic/media" ]
@@ -6269,11 +6235,6 @@
       "font_prewarmer_tab_helper.h",
       "fullscreen_win.cc",
       "icon_loader_win.cc",
-      "install_verification/win/module_info.h",
-      "install_verification/win/module_list.cc",
-      "install_verification/win/module_list.h",
-      "install_verification/win/module_verification_common.cc",
-      "install_verification/win/module_verification_common.h",
       "media/cdm_pref_service_helper.cc",
       "media/cdm_pref_service_helper.h",
       "media/media_foundation_service_monitor.cc",
@@ -6393,6 +6354,7 @@
       ":chrome_process_finder",
       "//chrome/app:chrome_exe_main_exports",
       "//chrome/app/theme:chrome_unscaled_resources_grit",
+      "//chrome/browser/install_verification:impl",
       "//chrome/browser/os_crypt",
       "//chrome/browser/platform_experience:prefs",
       "//chrome/browser/shortcuts",
@@ -8536,8 +8498,6 @@
 static_library("browser_generated_files") {
   public_deps = [
     ":buildflags",
-    "//chrome/browser:lcp_critical_path_predictor_proto",
-    "//chrome/browser:resource_prefetch_predictor_proto",
     "//chrome/browser/media:media_engagement_preload_proto",
     "//chrome/browser/media:mojo_bindings",
     "//chrome/browser/media/router/discovery/access_code:discovery_resources_proto",
@@ -8545,6 +8505,8 @@
     "//chrome/browser/net:probe_message_proto",
     "//chrome/browser/page_info:page_info_buildflags",
     "//chrome/browser/policy/messaging_layer/proto:log_upload_event_proto",
+    "//chrome/browser/predictors:resource_prefetch_predictor_proto",
+    "//chrome/browser/predictors/lcp_critical_path_predictor:lcp_critical_path_predictor_proto",
     "//chrome/browser/push_messaging:budget_proto",
     "//chrome/browser/regional_capabilities",
     "//chrome/browser/resource_coordinator:mojo_bindings",
@@ -8821,16 +8783,6 @@
   }
 }
 
-proto_library("resource_prefetch_predictor_proto") {
-  sources = [ "predictors/resource_prefetch_predictor.proto" ]
-}
-
-proto_library("lcp_critical_path_predictor_proto") {
-  sources = [
-    "predictors/lcp_critical_path_predictor/lcp_critical_path_predictor.proto",
-  ]
-}
-
 if (enable_bound_session_credentials) {
   proto_library("bound_session_credentials_proto") {
     sources = [
@@ -8981,10 +8933,6 @@
     "plugins/plugin_test_utils.h",
     "policy/messaging_layer/upload/fake_upload_client.cc",
     "policy/messaging_layer/upload/fake_upload_client.h",
-    "predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_test_util.cc",
-    "predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_test_util.h",
-    "predictors/loading_test_util.cc",
-    "predictors/loading_test_util.h",
     "resource_coordinator/tab_load_tracker_test_support.cc",
     "resource_coordinator/tab_load_tracker_test_support.h",
     "safe_browsing/notification_content_detection/mock_notification_content_detection_service.cc",
@@ -9010,6 +8958,7 @@
     "//chrome/browser/autofill:test_support",
     "//chrome/browser/media/webrtc",
     "//chrome/browser/notifications",
+    "//chrome/browser/predictors:test_support",
     "//chrome/browser/profiles:profile",
     "//chrome/browser/resource_coordinator",
     "//chrome/browser/safe_browsing:test_support",
@@ -9019,7 +8968,6 @@
   deps = [
     ":browser_process",
     ":global_features",
-    ":lcp_critical_path_predictor_proto",
     "//build:chromeos_buildflags",
     "//chrome/app/theme:theme_resources",
     "//chrome/browser/history",
diff --git a/chrome/browser/PRESUBMIT.py b/chrome/browser/PRESUBMIT.py
index a790d36..38f826b 100644
--- a/chrome/browser/PRESUBMIT.py
+++ b/chrome/browser/PRESUBMIT.py
@@ -406,6 +406,39 @@
 
     return []
 
+
+def _CheckNoNewEnableGlicUsage(input_api, output_api):
+    """Checks that there is no new usage of enable_glic or ENABLE_GLIC in
+    chrome/browser/.
+    """
+    problems = []
+    pattern = re.compile(r'\b(enable_glic|ENABLE_GLIC)\b')
+
+    for f in input_api.AffectedFiles(include_deletes=False):
+        if not f.UnixLocalPath().startswith('chrome/browser/') :
+            continue
+
+        if f.UnixLocalPath().endswith('PRESUBMIT.py'):
+            continue
+
+        for line_num, line in f.ChangedContents():
+            if pattern.search(line):
+                problems.append('  %s:%d:%s' %
+                                (f.LocalPath(), line_num, line.strip()))
+
+    if not problems:
+        return []
+
+    return [
+        output_api.PresubmitPromptWarning(
+            'New usage of "enable_glic" or "ENABLE_GLIC" found in '
+            'chrome/browser/. Ignore this warning if this might be a false '
+            'positive. Otherwise, revise the code to retain code blocks that '
+            'are ran when the flag is enabled. See crbug.com/486982086.',
+            items=problems)
+    ]
+
+
 ###############################################################################
 # Presubmit aggregator
 ###############################################################################
@@ -413,6 +446,7 @@
 def _CommonChecks(input_api, output_api):
     """Checks common to both upload and commit."""
     results = []
+    results.extend(_CheckNoNewEnableGlicUsage(input_api, output_api))
     results.extend(_CheckNewDirectoryHasBuildGn(input_api, output_api))
     results.extend(
         _CheckNoAutofillBrowserTestsWithoutAutofillBrowserTestEnvironment(
diff --git a/chrome/browser/PRESUBMIT_test.py b/chrome/browser/PRESUBMIT_test.py
index a44c5cc..ca822c2f 100755
--- a/chrome/browser/PRESUBMIT_test.py
+++ b/chrome/browser/PRESUBMIT_test.py
@@ -435,5 +435,74 @@
         self.assertEqual([], warnings)
 
 
+class CheckNoNewEnableGlicUsageTest(unittest.TestCase):
+    def testNewEnableGlicUsage(self):
+        mock_input_api = MockInputApi()
+        mock_input_api.files = [
+            MockAffectedFile('chrome/browser/foo.cc', ['if (enable_glic) {'], action='M'),
+        ]
+        mock_output_api = MockOutputApi()
+        warnings = PRESUBMIT._CheckNoNewEnableGlicUsage(
+            mock_input_api, mock_output_api)
+        self.assertEqual(1, len(warnings))
+        self.assertEqual(
+            'New usage of "enable_glic" or "ENABLE_GLIC" found in '
+            'chrome/browser/. Ignore this warning if this might be a false '
+            'positive. Otherwise, revise the code to retain code blocks that '
+            'are ran when the flag is enabled. See crbug.com/486982086.',
+            warnings[0].message)
+        self.assertEqual(1, len(warnings[0].items))
+
+    def testNewEnableGlicUsageUppercase(self):
+        mock_input_api = MockInputApi()
+        mock_input_api.files = [
+            MockAffectedFile('chrome/browser/foo.cc', ['#if defined(ENABLE_GLIC)'], action='M'),
+        ]
+        mock_output_api = MockOutputApi()
+        warnings = PRESUBMIT._CheckNoNewEnableGlicUsage(
+            mock_input_api, mock_output_api)
+        self.assertEqual(1, len(warnings))
+
+    def testNoEnableGlicUsage(self):
+        mock_input_api = MockInputApi()
+        mock_input_api.files = [
+            MockAffectedFile('chrome/browser/foo.cc', ['if (something_else) {'], action='M'),
+        ]
+        mock_output_api = MockOutputApi()
+        warnings = PRESUBMIT._CheckNoNewEnableGlicUsage(
+            mock_input_api, mock_output_api)
+        self.assertEqual([], warnings)
+
+    def testEnableGlicUsageOutsideChromeBrowser(self):
+        mock_input_api = MockInputApi()
+        mock_input_api.files = [
+            MockAffectedFile('chrome/common/foo.cc', ['if (enable_glic) {'], action='M'),
+        ]
+        mock_output_api = MockOutputApi()
+        warnings = PRESUBMIT._CheckNoNewEnableGlicUsage(
+            mock_input_api, mock_output_api)
+        self.assertEqual([], warnings)
+
+    def testEnableGlicUsageInPresubmit(self):
+        mock_input_api = MockInputApi()
+        mock_input_api.files = [
+            MockAffectedFile('chrome/browser/PRESUBMIT.py', ['if (enable_glic) {'], action='M'),
+        ]
+        mock_output_api = MockOutputApi()
+        warnings = PRESUBMIT._CheckNoNewEnableGlicUsage(
+            mock_input_api, mock_output_api)
+        self.assertEqual([], warnings)
+
+    def testEnableGlicUsageSubstring(self):
+        mock_input_api = MockInputApi()
+        mock_input_api.files = [
+            MockAffectedFile('chrome/browser/foo.cc', ['if (dont_enable_glic_v2) {'], action='M'),
+        ]
+        mock_output_api = MockOutputApi()
+        warnings = PRESUBMIT._CheckNoNewEnableGlicUsage(
+            mock_input_api, mock_output_api)
+        self.assertEqual([], warnings)
+
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 51bf209..87099ca 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -425,6 +425,18 @@
      switches::kPullToRefresh, "2"}};
 #endif  // USE_AURA
 
+#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
+const FeatureEntry::FeatureParam kDefaultBrowserPromptSurfaces_Infobar[] = {
+    {"prompt_surface", "infobar"}};
+const FeatureEntry::FeatureParam kDefaultBrowserPromptSurfaces_BubbleDialog[] =
+    {{"prompt_surface", "bubble_dialog"}};
+
+const FeatureEntry::FeatureVariation kDefaultBrowserPromptSurfacesVariations[] =
+    {{"with Infobar", kDefaultBrowserPromptSurfaces_Infobar, nullptr},
+     {"with Bubble Dialog", kDefaultBrowserPromptSurfaces_BubbleDialog,
+      nullptr}};
+#endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
+
 const FeatureEntry::FeatureParam kLocalNetworkAccessChecksBlock[] = {
     {"LocalNetworkAccessChecksWarn", "false"}};
 const FeatureEntry::FeatureVariation kLocalNetworkAccessChecksVariations[] = {
@@ -940,9 +952,6 @@
 const char kArcEnableVirtioBlkForDataInternalName[] =
     "arc-enable-virtio-blk-for-data";
 
-const char kProjectorServerSideSpeechRecognition[] =
-    "enable-projector-server-side-speech-recognition";
-
 const char kArcEnableAttestationFlag[] = "arc-enable-attestation";
 
 #endif  // BUILDFLAG(IS_CHROMEOS)
@@ -8050,10 +8059,6 @@
      kOsCrOS,
      FEATURE_VALUE_TYPE(features::kEnableNearbyBluetoothClassicAdvertising)},
 
-    {"nearby-mdns", flag_descriptions::kEnableNearbyMdnsName,
-     flag_descriptions::kEnableNearbyMdnsDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(features::kEnableNearbyMdns)},
-
     {"nearby-presence", flag_descriptions::kNearbyPresenceName,
      flag_descriptions::kNearbyPresenceDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kNearbyPresence)},
@@ -9336,12 +9341,6 @@
      flag_descriptions::kProjectorAppDebugDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kProjectorAppDebug)},
 
-    {kProjectorServerSideSpeechRecognition,
-     flag_descriptions::kProjectorServerSideSpeechRecognitionName,
-     flag_descriptions::kProjectorServerSideSpeechRecognitionDescription,
-     kOsCrOS,
-     FEATURE_VALUE_TYPE(ash::features::kInternalServerSideSpeechRecognition)},
-
     {"enable-projector-server-side-usm",
      flag_descriptions::kProjectorServerSideUsmName,
      flag_descriptions::kProjectorServerSideUsmDescription, kOsCrOS,
@@ -10840,6 +10839,9 @@
     {"glic-capture-region", flag_descriptions::kGlicCaptureRegionName,
      flag_descriptions::kGlicCaptureRegionDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kGlicCaptureRegion)},
+    {"glic-chrome-status-icon", flag_descriptions::kGlicChromeStatusIconName,
+     flag_descriptions::kGlicChromeStatusIconDescription, kOsMac,
+     FEATURE_VALUE_TYPE(features::kGlicChromeStatusIcon)},
     {"glic-daisy-chain-new-tabs", flag_descriptions::kGlicDaisyChainNewTabsName,
      flag_descriptions::kGlicDaisyChainNewTabsDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kGlicDaisyChainNewTabs)},
@@ -11182,6 +11184,14 @@
      flag_descriptions::kDefaultBrowserFrameworkName,
      flag_descriptions::kDefaultBrowserFrameworkDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(default_browser::kDefaultBrowserFramework)},
+
+    {"default-browser-prompt-surfaces",
+     flag_descriptions::kDefaultBrowserPromptSurfacesName,
+     flag_descriptions::kDefaultBrowserPromptSurfacesDescription, kOsDesktop,
+     FEATURE_WITH_PARAMS_VALUE_TYPE(
+         default_browser::kDefaultBrowserPromptSurfaces,
+         kDefaultBrowserPromptSurfacesVariations,
+         "DefaultBrowserPromptSurfaces")},
 #endif  // !BUILDFLAG(IS_ANDROID) && ! BUILDFLAG(IS_CHROMEOS)
 
     {"privacy-sandbox-ad-topics-content-parity",
@@ -12974,6 +12984,11 @@
      FEATURE_VALUE_TYPE(tabs::kHorizontalTabStripComboButton)},
 #endif  // BUILDFLAG(IS_ANDROID)
 
+#if BUILDFLAG(IS_ANDROID)
+    {"ntp-mvc-refactor", flag_descriptions::kNtpMvcRefactorName,
+     flag_descriptions::kNtpMvcRefactorDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kNtpMvcRefactor)},
+#endif
     // Add new entries above this line.
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
@@ -13078,16 +13093,6 @@
                                        const FeatureEntry& entry) {
 #if BUILDFLAG(IS_CHROMEOS)
   version_info::Channel channel = chrome::GetChannel();
-  // enable-projector-server-side-speech-recognition is only available in Chrome
-  // branded builds.
-  if (std::string_view(kProjectorServerSideSpeechRecognition) ==
-      entry.internal_name) {
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-    return false;
-#else
-    return true;
-#endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
-  }
 
   // enable-ui-devtools is only available on for non Stable channels.
   if (std::string_view(ui_devtools::switches::kEnableUiDevTools) ==
diff --git a/chrome/browser/actor/android/java/src/org/chromium/chrome/browser/actor/ui/ActorOverlayCoordinatorTest.java b/chrome/browser/actor/android/java/src/org/chromium/chrome/browser/actor/ui/ActorOverlayCoordinatorTest.java
index b4dc8489..c8da3fbd 100644
--- a/chrome/browser/actor/android/java/src/org/chromium/chrome/browser/actor/ui/ActorOverlayCoordinatorTest.java
+++ b/chrome/browser/actor/android/java/src/org/chromium/chrome/browser/actor/ui/ActorOverlayCoordinatorTest.java
@@ -11,12 +11,14 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.supplier.ObservableSuppliers;
@@ -43,9 +45,10 @@
     private ActorOverlayCoordinator mCoordinator;
     private SettableNullableObservableSupplier<Tab> mCurrentTabSupplier;
 
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         Mockito.when(mViewStub.inflate()).thenReturn(mView);
 
         mTabObscuringHandler = new TabObscuringHandler();
diff --git a/chrome/browser/actor/execution_engine.cc b/chrome/browser/actor/execution_engine.cc
index bd72ffc..e83b2cda 100644
--- a/chrome/browser/actor/execution_engine.cc
+++ b/chrome/browser/actor/execution_engine.cc
@@ -760,7 +760,7 @@
   const GURL& url =
       tab->GetContents()->GetPrimaryMainFrame()->GetLastCommittedURL();
   if (safety_list_manager.get_blocked_list()
-          .ContainsPatternMatchingSelfNavigation(url)) {
+          .ContainsEntryMatchingSelfNavigation(url)) {
     OnMayActOnTabDecision(
         tab->GetContents()->GetPrimaryMainFrame()->GetLastCommittedOrigin(),
         MayActOnUrlBlockReason::kBlockedByStaticList);
diff --git a/chrome/browser/actor/safety_list.cc b/chrome/browser/actor/safety_list.cc
index e759479..a9d6360 100644
--- a/chrome/browser/actor/safety_list.cc
+++ b/chrome/browser/actor/safety_list.cc
@@ -19,28 +19,29 @@
 
 bool SafetyList::ContainsUrlPair(const GURL& source,
                                  const GURL& destination) const {
-  return std::ranges::any_of(patterns_, [&](const SafetyListPatterns& pattern) {
-    return pattern.source.Matches(source) &&
-           pattern.destination.Matches(destination);
+  return std::ranges::any_of(entries_, [&](const SafetyListEntry& entry) {
+    return entry.source.Matches(source) &&
+           entry.destination.Matches(destination);
   });
 }
 
 bool SafetyList::ContainsUrlPairWithWildcardSource(
     const GURL& source,
     const GURL& destination) const {
-  return std::ranges::any_of(patterns_, [&](const SafetyListPatterns& pattern) {
+  return std::ranges::any_of(entries_, [&](const SafetyListEntry& entry) {
     // A full wildcard [*] is not included in `HasDomainWildcard()`, so we check
     // for that as well.
     bool has_domain_wildcard =
-        pattern.source.GetScope() ==
+        entry.source.GetScope() ==
             ContentSettingsPattern::Scope::kFullWildcard ||
-        pattern.source.HasDomainWildcard();
-    return has_domain_wildcard && pattern.source.Matches(source) &&
-           pattern.destination.Matches(destination);
+        entry.source.HasDomainWildcard();
+    return has_domain_wildcard && entry.source.Matches(source) &&
+           entry.destination.Matches(destination);
   });
 }
 
-SafetyList::SafetyList(Patterns patterns) : patterns_(std::move(patterns)) {}
+SafetyList::SafetyList(std::vector<SafetyListEntry> entries)
+    : entries_(std::move(entries)) {}
 
 SafetyList::~SafetyList() = default;
 
@@ -49,8 +50,9 @@
 
 // static
 base::expected<SafetyList, SafetyListParseResult>
-SafetyList::ParsePatternListFromJson(const base::ListValue& list_data) {
-  Patterns patterns;
+SafetyList::ParseEntriesFromJson(const base::ListValue& list_data) {
+  std::vector<SafetyListEntry> entries;
+  entries.reserve(list_data.size());
   for (const auto& navigation : list_data) {
     const base::DictValue* navigation_dict = navigation.GetIfDict();
     if (!navigation_dict) {
@@ -58,7 +60,7 @@
           SafetyListParseResult::kJsonListValueNotADictionary);
     }
 
-    // Only parse pattern pair if both fields exist.
+    // Only parse entry if both fields exist.
     const std::string* from = navigation_dict->FindString("from");
     if (!from) {
       return base::unexpected(SafetyListParseResult::kInvalidFromField);
@@ -77,10 +79,10 @@
     if (!destination.IsValid()) {
       return base::unexpected(SafetyListParseResult::kInvalidToUrlPattern);
     }
-    patterns.push_back(
-        SafetyListPatterns{std::move(source), std::move(destination)});
+    entries.push_back(
+        SafetyListEntry{std::move(source), std::move(destination)});
   }
-  return SafetyList(std::move(patterns));
+  return SafetyList(std::move(entries));
 }
 
 }  // namespace actor
diff --git a/chrome/browser/actor/safety_list.h b/chrome/browser/actor/safety_list.h
index 9d6d8c0..3ec07d0 100644
--- a/chrome/browser/actor/safety_list.h
+++ b/chrome/browser/actor/safety_list.h
@@ -40,28 +40,26 @@
 };
 // LINT.ThenChange(//tools/metrics/histograms/metadata/actor/enums.xml:SafetyListParseResult)
 
-struct SafetyListPatterns {
+struct SafetyListEntry {
   ContentSettingsPattern source;
   ContentSettingsPattern destination;
 
-  friend bool operator==(const SafetyListPatterns&,
-                         const SafetyListPatterns&) = default;
+  friend bool operator==(const SafetyListEntry&,
+                         const SafetyListEntry&) = default;
 };
 
 class SafetyList {
  public:
-  using Patterns = std::vector<SafetyListPatterns>;
-
-  explicit SafetyList(Patterns patterns = {});
+  explicit SafetyList(std::vector<SafetyListEntry> entries = {});
 
   ~SafetyList();
 
   SafetyList(const SafetyList&);
   SafetyList& operator=(const SafetyList&);
 
-  const Patterns& patterns() const { return patterns_; }
+  const std::vector<SafetyListEntry>& entries() const { return entries_; }
 
-  size_t size() const { return patterns_.size(); }
+  size_t size() const { return entries_.size(); }
 
   bool ContainsUrlPairWithWildcardSource(const GURL& source,
                                          const GURL& destination) const;
@@ -76,20 +74,20 @@
   // Just in case, to prevent rules which do not have wildcard in their
   // `source` from erroneously applying, we still pass `url` as the `source`
   // argument for ContainsUrlPair.
-  bool ContainsPatternMatchingSelfNavigation(const GURL& url) const {
+  bool ContainsEntryMatchingSelfNavigation(const GURL& url) const {
     return ContainsUrlPair(url, url);
   }
 
-  // Parses a list of patterns from a JSON list. Returns the parsed SafetyList
+  // Parses a list of entries from a JSON list. Returns the parsed SafetyList
   // on success, or a SafetyListParseResult on failure. If the result is a
   // SafetyListParseResult, the enum value is guaranteed to not be `kSuccess`.
-  static base::expected<SafetyList, SafetyListParseResult>
-  ParsePatternListFromJson(const base::ListValue& list_data);
+  static base::expected<SafetyList, SafetyListParseResult> ParseEntriesFromJson(
+      const base::ListValue& list_data);
 
   friend bool operator==(const SafetyList&, const SafetyList&) = default;
 
  private:
-  Patterns patterns_;
+  std::vector<SafetyListEntry> entries_;
 };
 
 }  // namespace actor
diff --git a/chrome/browser/actor/safety_list_manager.cc b/chrome/browser/actor/safety_list_manager.cc
index 66ae1fe..6cbc814 100644
--- a/chrome/browser/actor/safety_list_manager.cc
+++ b/chrome/browser/actor/safety_list_manager.cc
@@ -30,13 +30,13 @@
 constexpr std::string_view kBlockedHistogramName =
     "Actor.SafetyListParseResult.NavigationBlocked";
 
-void MaybeAppendHardcodedPatterns(SafetyList::Patterns& patterns) {
+void MaybeAppendHardcodedEntries(std::vector<SafetyListEntry>& entries) {
   if (IsNavigationGatingEnabled() &&
       kGlicIncludeHardcodedBlockListEntries.Get()) {
-    patterns.emplace_back(
+    entries.emplace_back(
         ContentSettingsPattern::FromString("*"),
         ContentSettingsPattern::FromString("[*.]googleplex.com"));
-    patterns.emplace_back(
+    entries.emplace_back(
         ContentSettingsPattern::FromString("*"),
         ContentSettingsPattern::FromString("[*.]corp.google.com"));
   }
@@ -56,9 +56,9 @@
 }
 
 SafetyListManager::SafetyListManager() {
-  SafetyList::Patterns patterns;
-  MaybeAppendHardcodedPatterns(patterns);
-  blocked_ = SafetyList(std::move(patterns));
+  std::vector<SafetyListEntry> entries;
+  MaybeAppendHardcodedEntries(entries);
+  blocked_ = SafetyList(std::move(entries));
 }
 SafetyListManager::~SafetyListManager() = default;
 
@@ -81,7 +81,7 @@
       -> base::expected<SafetyList, SafetyListParseResult> {
     if (const base::Value* value = json_dict->Find(field_name)) {
       if (const base::ListValue* list = value->GetIfList()) {
-        return SafetyList::ParsePatternListFromJson(*list);
+        return SafetyList::ParseEntriesFromJson(*list);
       }
       return base::unexpected(SafetyListParseResult::kJsonKeyValueNotAList);
     }
@@ -97,9 +97,9 @@
   base::expected<SafetyList, SafetyListParseResult> blocked_result =
       parse_one_list(kBlockedFieldName);
   if (blocked_result.has_value()) {
-    SafetyList::Patterns patterns = blocked_result->patterns();
-    MaybeAppendHardcodedPatterns(patterns);
-    blocked_ = SafetyList(std::move(patterns));
+    std::vector<SafetyListEntry> entries = blocked_result->entries();
+    MaybeAppendHardcodedEntries(entries);
+    blocked_ = SafetyList(std::move(entries));
   }
 
   return {allowed_result.error_or(SafetyListParseResult::kSuccess),
diff --git a/chrome/browser/actor/safety_list_unittest.cc b/chrome/browser/actor/safety_list_unittest.cc
index f4d3c42..fa311347 100644
--- a/chrome/browser/actor/safety_list_unittest.cc
+++ b/chrome/browser/actor/safety_list_unittest.cc
@@ -121,7 +121,7 @@
   };
 
   for (const auto& test_case : kTestCases) {
-    SafetyList::Patterns list;
+    std::vector<SafetyListEntry> list;
     list.push_back({test_case.source_pattern, test_case.destination_pattern});
     SCOPED_TRACE(test_case.desc);
     EXPECT_EQ(test_case.expected,
@@ -131,7 +131,7 @@
 }
 
 TEST(SafetyListTest, ContainsUrlPair_MultipleEntries) {
-  SafetyList::Patterns list;
+  std::vector<SafetyListEntry> list;
   list.push_back({ContentSettingsPattern::FromString("a.com"),
                   ContentSettingsPattern::FromString("b.com")});
   list.push_back({ContentSettingsPattern::FromString("c.com"),
@@ -193,7 +193,7 @@
 
   for (const auto& test_case : kTestCases) {
     SCOPED_TRACE(test_case.desc);
-    EXPECT_THAT(SafetyList::ParsePatternListFromJson(
+    EXPECT_THAT(SafetyList::ParseEntriesFromJson(
                     base::test::ParseJsonList(test_case.json)),
                 test_case.matches);
   }
@@ -267,7 +267,7 @@
   };
 
   for (const auto& test_case : kTestCases) {
-    SafetyList::Patterns list;
+    std::vector<SafetyListEntry> list;
     list.push_back({test_case.source_pattern, test_case.destination_pattern});
     SCOPED_TRACE(test_case.desc);
     EXPECT_EQ(test_case.expected,
@@ -350,11 +350,11 @@
   };
 
   for (const auto& test_case : kTestCases) {
-    SafetyList::Patterns list;
+    std::vector<SafetyListEntry> list;
     list.push_back({test_case.source_pattern, test_case.destination_pattern});
     SCOPED_TRACE(test_case.desc);
     EXPECT_EQ(test_case.expected,
-              SafetyList(list).ContainsPatternMatchingSelfNavigation(
+              SafetyList(list).ContainsEntryMatchingSelfNavigation(
                   GURL(test_case.url)));
   }
 }
diff --git a/chrome/browser/actor/ui/BUILD.gn b/chrome/browser/actor/ui/BUILD.gn
index e8fcdb4..a82a5d2 100644
--- a/chrome/browser/actor/ui/BUILD.gn
+++ b/chrome/browser/actor/ui/BUILD.gn
@@ -73,47 +73,67 @@
   webui_module_path = "/"
 }
 
-if (!skip_android_unmigrated_actor_files) {
-  source_set("actor_overlay") {
+if (!is_android) {
+  source_set("actor_overlay_web_view") {
     sources = [
-      "actor_overlay_handler.cc",
-      "actor_overlay_handler.h",
-      "actor_overlay_ui.cc",
-      "actor_overlay_ui.h",
       "actor_overlay_web_view.cc",
       "actor_overlay_web_view.h",
     ]
     deps = [
-      ":mojo_bindings",
-      ":ui",
+      ":actor_overlay",
       "//base",
-      "//chrome/browser/actor/resources:grit_grit",
       "//chrome/browser/profiles",
-      "//chrome/browser/resources/actor_overlay:resources",
-      "//chrome/browser/themes",
       "//chrome/browser/ui/browser_window",
-      "//chrome/browser/ui/color:color_headers",
-      "//chrome/browser/ui/tabs:tabs_public",
       "//chrome/browser/ui/webui",
       "//chrome/browser/ui/webui:webui_util",
-      "//chrome/common",
+      "//chrome/common:chrome_features",
       "//components/tabs:public",
       "//content/public/browser",
-      "//mojo/public/cpp/bindings",
-      "//skia",
-      "//ui/base",
-      "//ui/color",
-      "//ui/native_theme",
       "//ui/views",
       "//ui/views/controls/webview",
-      "//ui/webui",
     ]
   }
+}
 
+source_set("actor_overlay") {
+  sources = [
+    "actor_overlay_handler.cc",
+    "actor_overlay_handler.h",
+    "actor_overlay_ui.cc",
+    "actor_overlay_ui.h",
+  ]
+  deps = [
+    ":mojo_bindings",
+    ":ui",
+    "//base",
+    "//chrome/browser/actor/resources:grit_grit",
+    "//chrome/browser/profiles",
+    "//chrome/browser/resources/actor_overlay:resources",
+    "//chrome/browser/ui/color:color_headers",
+    "//chrome/browser/ui/tabs:tabs_public",
+    "//chrome/browser/ui/webui",
+    "//chrome/browser/ui/webui:webui_util",
+    "//chrome/common",
+    "//components/tabs:public",
+    "//content/public/browser",
+    "//mojo/public/cpp/bindings",
+    "//skia",
+    "//ui/color",
+    "//ui/native_theme",
+    "//ui/webui",
+  ]
+
+  if (!is_android) {
+    deps += [ "//chrome/browser/themes" ]
+  }
+}
+
+if (!skip_android_unmigrated_actor_files) {
   source_set("window_controller_impl") {
     sources = [ "actor_ui_window_controller.cc" ]
     deps = [
       ":actor_overlay",
+      ":actor_overlay_web_view",
       ":metrics",
       ":ui",
       "//chrome/browser/actor",
@@ -190,6 +210,7 @@
 
     deps = [
       ":actor_overlay",
+      ":actor_overlay_web_view",
       ":dom_node_geometry",
       ":ui",
       ":ui_event_types",
@@ -375,6 +396,7 @@
     ]
     deps += [
       ":actor_overlay",
+      ":actor_overlay_web_view",
       ":event_dispatcher",
       ":test_support",
       ":ui",
diff --git a/chrome/browser/actor/ui/actor_overlay_handler.cc b/chrome/browser/actor/ui/actor_overlay_handler.cc
index 2987298..1fb64a2 100644
--- a/chrome/browser/actor/ui/actor_overlay_handler.cc
+++ b/chrome/browser/actor/ui/actor_overlay_handler.cc
@@ -6,7 +6,6 @@
 
 #include "chrome/browser/actor/ui/actor_ui_tab_controller_interface.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/webui/webui_embedding_context.h"
 #include "chrome/common/chrome_features.h"
@@ -15,6 +14,10 @@
 #include "ui/color/color_provider.h"
 #include "ui/native_theme/native_theme.h"
 
+#if !BUILDFLAG(IS_ANDROID)
+#include "chrome/browser/themes/theme_service_factory.h"
+#endif
+
 namespace actor::ui {
 
 ActorOverlayHandler::ActorOverlayHandler(
@@ -22,16 +25,20 @@
     mojo::PendingReceiver<mojom::ActorOverlayPageHandler> receiver,
     content::WebContents* web_contents)
     : web_contents_(web_contents),
+#if !BUILDFLAG(IS_ANDROID)
       theme_service_(ThemeServiceFactory::GetForProfile(
           Profile::FromBrowserContext(web_contents->GetBrowserContext()))),
+#endif
       page_(std::move(page)),
       receiver_{this, std::move(receiver)} {
   native_theme_observation_.Observe(
       ::ui::NativeTheme::GetInstanceForNativeUi());
+#if !BUILDFLAG(IS_ANDROID)
   theme_service_observation_.Observe(theme_service_);
+#endif
 
   // Trigger the initial theme color.
-  OnThemeChanged();
+  UpdateActorTheme();
 }
 
 ActorOverlayHandler::~ActorOverlayHandler() = default;
@@ -41,10 +48,12 @@
     return;
   }
   is_hovering_ = is_hovering;
+#if !BUILDFLAG(IS_ANDROID)
   if (auto* tab_controller = ActorUiTabControllerInterface::From(
           webui::GetTabInterface(web_contents_))) {
     tab_controller->OnOverlayHoverStatusChanged(is_hovering);
   }
+#endif
 }
 
 void ActorOverlayHandler::GetCurrentBorderGlowVisibility(
@@ -73,10 +82,16 @@
 
 void ActorOverlayHandler::OnNativeThemeUpdated(
     ::ui::NativeTheme* observed_theme) {
-  OnThemeChanged();
+  UpdateActorTheme();
 }
 
+#if !BUILDFLAG(IS_ANDROID)
 void ActorOverlayHandler::OnThemeChanged() {
+  UpdateActorTheme();
+}
+#endif
+
+void ActorOverlayHandler::UpdateActorTheme() {
   if (base::FeatureList::IsEnabled(features::kActorUiThemed)) {
     auto theme = mojom::Theme::New();
     const ::ui::ColorProvider& color_provider =
diff --git a/chrome/browser/actor/ui/actor_overlay_handler.h b/chrome/browser/actor/ui/actor_overlay_handler.h
index c61ec15..ab7dcfb7 100644
--- a/chrome/browser/actor/ui/actor_overlay_handler.h
+++ b/chrome/browser/actor/ui/actor_overlay_handler.h
@@ -7,13 +7,16 @@
 
 #include "base/scoped_observation.h"
 #include "chrome/browser/actor/ui/actor_overlay.mojom.h"
-#include "chrome/browser/themes/theme_service.h"
-#include "chrome/browser/themes/theme_service_observer.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "ui/native_theme/native_theme.h"
 #include "ui/native_theme/native_theme_observer.h"
 
+#if !BUILDFLAG(IS_ANDROID)
+#include "chrome/browser/themes/theme_service.h"
+#include "chrome/browser/themes/theme_service_observer.h"
+#endif
+
 namespace content {
 class WebContents;
 }  // namespace content
@@ -21,7 +24,9 @@
 namespace actor::ui {
 
 class ActorOverlayHandler : public mojom::ActorOverlayPageHandler,
+#if !BUILDFLAG(IS_ANDROID)
                             public ThemeServiceObserver,
+#endif
                             public ::ui::NativeThemeObserver {
  public:
   ActorOverlayHandler(
@@ -59,16 +64,25 @@
  private:
   // ui::NativeThemeObserver:
   void OnNativeThemeUpdated(::ui::NativeTheme* observed_theme) override;
+#if !BUILDFLAG(IS_ANDROID)
   // ThemeServiceObserver:
   void OnThemeChanged() override;
+#endif
+  // Sets the theme colors for the actor overlay.
+  void UpdateActorTheme();
   // Is the user hovering over the actor overlay.
   bool is_hovering_ = false;
   raw_ptr<content::WebContents> web_contents_ = nullptr;
+#if !BUILDFLAG(IS_ANDROID)
   raw_ptr<ThemeService> theme_service_;
+#endif
   base::ScopedObservation<::ui::NativeTheme, ::ui::NativeThemeObserver>
       native_theme_observation_{this};
+
+#if !BUILDFLAG(IS_ANDROID)
   base::ScopedObservation<ThemeService, ThemeServiceObserver>
       theme_service_observation_{this};
+#endif
 
   mojo::Remote<mojom::ActorOverlayPage> page_;
   mojo::Receiver<mojom::ActorOverlayPageHandler> receiver_{this};
diff --git a/chrome/browser/actor/ui/actor_ui_tab_controller.h b/chrome/browser/actor/ui/actor_ui_tab_controller.h
index 5f1e023..7b49bd6 100644
--- a/chrome/browser/actor/ui/actor_ui_tab_controller.h
+++ b/chrome/browser/actor/ui/actor_ui_tab_controller.h
@@ -28,21 +28,22 @@
   // ActorUiTabControllerInterface:
   void OnUiTabStateChange(const UiTabState& ui_tab_state,
                           UiResultCallback callback) override;
-  void OnWebContentsAttached() override;
-  void OnViewBoundsChanged() override;
   void SetActorTaskPaused() override;
   void SetActorTaskResume() override;
+  base::WeakPtr<ActorUiTabControllerInterface> GetWeakPtr() override;
+  UiTabState GetCurrentUiTabState() const override;
+
+#if !BUILDFLAG(IS_ANDROID)
+  void OnWebContentsAttached() override;
+  void OnViewBoundsChanged() override;
   void OnOverlayHoverStatusChanged(bool is_hovering) override;
   void OnHandoffButtonHoverStatusChanged() override;
   void OnHandoffButtonFocusStatusChanged() override;
   [[nodiscard]] base::ScopedClosureRunner RegisterHandoffButtonController(
       HandoffButtonController* controller) override;
-  UiTabState GetCurrentUiTabState() const override;
 
   void OnImmersiveModeChanged() override;
 
-  base::WeakPtr<ActorUiTabControllerInterface> GetWeakPtr() override;
-
   [[nodiscard]] base::ScopedClosureRunner
   RegisterActorTabIndicatorStateChangedCallback(
       ActorTabIndicatorStateChangedCallback callback) override;
@@ -50,6 +51,7 @@
       ActorOverlayStateChangeCallback callback) override;
   [[nodiscard]] base::ScopedClosureRunner RegisterActorOverlayBackgroundChange(
       ActorOverlayBackgroundChangeCallback callback) override;
+#endif
 
  private:
   // Called only once on startup to initialize tab subscriptions.
@@ -70,8 +72,10 @@
   // Run the test callback after updates have been made.
   void OnUpdateFinished();
 
+#if !BUILDFLAG(IS_ANDROID)
   // Called when the omnibox's popup visibility changes.
   void OnWindowOmniboxPopupVisibilityChanged() override;
+#endif
 
   // Sets the Tab Indicator visibility.
   void SetActorTabIndicatorVisibility(TabIndicatorStatus tab_indicator_status,
@@ -112,11 +116,13 @@
   // Holds subscriptions for TabInterface callbacks.
   std::vector<base::CallbackListSubscription> tab_subscriptions_;
 
+#if !BUILDFLAG(IS_ANDROID)
   ActorTabIndicatorStateChangedCallback
       on_actor_tab_indicator_changed_callback_;
   ActorOverlayStateChangeCallback on_actor_overlay_state_changed_callback_;
   ActorOverlayBackgroundChangeCallback
       actor_overlay_background_changed_callback_;
+#endif
 
   // The Actor Keyed Service for the associated profile.
   raw_ptr<ActorKeyedService> actor_keyed_service_ = nullptr;
diff --git a/chrome/browser/actor/ui/actor_ui_window_controller_unittest.cc b/chrome/browser/actor/ui/actor_ui_window_controller_unittest.cc
index 6e6b515..cecd349 100644
--- a/chrome/browser/actor/ui/actor_ui_window_controller_unittest.cc
+++ b/chrome/browser/actor/ui/actor_ui_window_controller_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/test/test_future.h"
 #include "chrome/browser/actor/ui/actor_overlay_web_view.h"
 #include "chrome/browser/ui/browser_window/test/mock_browser_window_interface.h"
+#include "chrome/test/base/chrome_test_utils.h"
 #include "chrome/test/views/chrome_views_test_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/unowned_user_data/unowned_user_data_host.h"
@@ -25,7 +26,9 @@
 using ::testing::Return;
 using ::testing::ReturnRef;
 
-class ActorUiContentsContainerControllerTest : public ChromeViewsTestBase {
+class ActorUiContentsContainerControllerTest
+    : public chrome_test_utils::TestingBrowserProcessDeathTestMixin,
+      public ChromeViewsTestBase {
  public:
   void SetUp() override {
     ChromeViewsTestBase::SetUp();
diff --git a/chrome/browser/ai/ai_language_model.cc b/chrome/browser/ai/ai_language_model.cc
index 4bc1471..319d52d 100644
--- a/chrome/browser/ai/ai_language_model.cc
+++ b/chrome/browser/ai/ai_language_model.cc
@@ -207,9 +207,9 @@
     }
   }
 
-  void OnQuotaOverflow() {
+  void OnContextOverflow() {
     if (responder_) {
-      responder_->OnQuotaOverflow();
+      responder_->OnContextOverflow();
     }
   }
 
@@ -867,16 +867,17 @@
 
   auto space_reserved = context_->ReserveSpace(*token_count);
   if (space_reserved == Context::SpaceReservationResult::kInsufficientSpace) {
-    auto quota = context_->GetAvailableTokens();
+    auto available_tokens = context_->GetAvailableTokens();
     prompt_state_->OnError(
         blink::mojom::ModelStreamingResponseStatus::kErrorInputTooLarge,
-        blink::mojom::QuotaErrorInfo::New(token_count.value(), quota));
+        blink::mojom::QuotaErrorInfo::New(token_count.value(),
+                                          available_tokens));
     return;
   }
 
   if (space_reserved == Context::SpaceReservationResult::kSpaceMadeAvailable) {
     HandleOverflow();
-    prompt_state_->OnQuotaOverflow();
+    prompt_state_->OnContextOverflow();
   }
 
   // Use a cloned version of the current session so it is easy to restore to
@@ -935,7 +936,7 @@
     // will process the context including `model_output`, so it can be ignored
     // here.
     HandleOverflow();
-    responder->OnQuotaOverflow();
+    responder->OnContextOverflow();
   } else if (model_output) {
     // Add the output to the session since this is not added automatically from
     // the Generate() call. The previous token will be a kModel token from
diff --git a/chrome/browser/ai/ai_language_model_unittest.cc b/chrome/browser/ai/ai_language_model_unittest.cc
index b5cf223a..b353e22 100644
--- a/chrome/browser/ai/ai_language_model_unittest.cc
+++ b/chrome/browser/ai/ai_language_model_unittest.cc
@@ -668,7 +668,7 @@
   std::string long_prompt(kTestMaxTokens / 3, 'a');
   AITestUtils::TestStreamingResponder responder;
   session->Prompt(MakeInput(long_prompt), nullptr, responder.BindRemote());
-  responder.WaitForQuotaOverflow();
+  responder.WaitForContextOverflow();
   EXPECT_TRUE(responder.WaitForCompletion());
   // Response should include input/output of previous prompt with the original
   // long prompt not present.
@@ -687,7 +687,7 @@
   std::string long_prompt(kTestMaxTokens / 3, 'a');
   AITestUtils::TestStreamingResponder responder;
   session->Append(MakeInput(long_prompt), responder.BindRemote());
-  responder.WaitForQuotaOverflow();
+  responder.WaitForContextOverflow();
   EXPECT_TRUE(responder.WaitForCompletion());
 
   EXPECT_THAT(Prompt(*session, MakeInput("foo")),
@@ -713,7 +713,7 @@
 
   AITestUtils::TestStreamingResponder responder;
   session->Prompt(MakeInput("foo"), nullptr, responder.BindRemote());
-  responder.WaitForQuotaOverflow();
+  responder.WaitForContextOverflow();
   EXPECT_TRUE(responder.WaitForCompletion());
   EXPECT_THAT(responder.responses(), ElementsAre(long_response));
 
diff --git a/chrome/browser/ai/ai_test_utils.cc b/chrome/browser/ai/ai_test_utils.cc
index 7ac799ab..be0bbf9 100644
--- a/chrome/browser/ai/ai_test_utils.cc
+++ b/chrome/browser/ai/ai_test_utils.cc
@@ -23,8 +23,8 @@
   return !error_status_.has_value();
 }
 
-void AITestUtils::TestStreamingResponder::WaitForQuotaOverflow() {
-  quota_overflow_run_loop_.Run();
+void AITestUtils::TestStreamingResponder::WaitForContextOverflow() {
+  context_overflow_run_loop_.Run();
 }
 
 void AITestUtils::TestStreamingResponder::OnError(
@@ -47,8 +47,8 @@
   run_loop_.Quit();
 }
 
-void AITestUtils::TestStreamingResponder::OnQuotaOverflow() {
-  quota_overflow_run_loop_.Quit();
+void AITestUtils::TestStreamingResponder::OnContextOverflow() {
+  context_overflow_run_loop_.Quit();
 }
 
 AITestUtils::AITestBase::AITestBase()
diff --git a/chrome/browser/ai/ai_test_utils.h b/chrome/browser/ai/ai_test_utils.h
index 45f5c0c..2af12a7 100644
--- a/chrome/browser/ai/ai_test_utils.h
+++ b/chrome/browser/ai/ai_test_utils.h
@@ -40,7 +40,7 @@
     // Returns true on successful completion and false on error.
     bool WaitForCompletion();
 
-    void WaitForQuotaOverflow();
+    void WaitForContextOverflow();
 
     blink::mojom::ModelStreamingResponseStatus error_status() const {
       EXPECT_TRUE(error_status_.has_value());
@@ -67,14 +67,14 @@
     void OnStreaming(const std::string& text) override;
     void OnCompletion(
         blink::mojom::ModelExecutionContextInfoPtr context_info) override;
-    void OnQuotaOverflow() override;
+    void OnContextOverflow() override;
 
     std::optional<blink::mojom::ModelStreamingResponseStatus> error_status_;
     blink::mojom::QuotaErrorInfoPtr quota_error_info_;
     std::vector<std::string> responses_;
     uint64_t current_tokens_ = 0;
     base::RunLoop run_loop_;
-    base::RunLoop quota_overflow_run_loop_;
+    base::RunLoop context_overflow_run_loop_;
     mojo::Receiver<blink::mojom::ModelStreamingResponder> receiver_{this};
   };
 
diff --git a/chrome/browser/android/compositor/tab_content_manager.cc b/chrome/browser/android/compositor/tab_content_manager.cc
index 248e629..fb91e2e 100644
--- a/chrome/browser/android/compositor/tab_content_manager.cc
+++ b/chrome/browser/android/compositor/tab_content_manager.cc
@@ -61,28 +61,47 @@
 // leak memory or cause callbacks to hang indefinitely.
 const base::TimeDelta kTabReadbackTimeout = base::Seconds(15);
 
+content::RenderWidgetHostView* GetRwhv(content::WebContents* web_contents) {
+  content::RenderViewHost* rvh = web_contents->GetRenderViewHost();
+  if (!rvh) {
+    return nullptr;
+  }
+  content::RenderWidgetHost* rwh = rvh->GetWidget();
+  return rwh ? rwh->GetView() : nullptr;
+}
+
 }  // namespace
 
 namespace android {
 
 class TabContentManager::TabReadbackRequest {
  public:
-  TabReadbackRequest(content::RenderWidgetHostView* rwhv,
+  TabReadbackRequest(content::WebContents* web_contents,
                      float thumbnail_scale,
                      TabReadbackCallback end_callback)
       : thumbnail_scale_(thumbnail_scale),
         end_callback_(std::move(end_callback)) {
-    DCHECK(rwhv);
     auto result_callback =
         base::BindOnce(&TabReadbackRequest::OnFinishGetTabThumbnailBitmap,
                        weak_factory_.GetWeakPtr());
 
+    decrementor_ = web_contents->IncrementCapturerCount(
+        gfx::Size(), /*stay_hidden=*/true, /*stay_awake=*/false,
+        /*is_activity=*/false);
+
+    auto* rwhv = GetRwhv(web_contents);
+    if (!rwhv || !rwhv->IsSurfaceAvailableForCopy()) {
+      std::move(result_callback).Run(viz::CopyOutputBitmapWithMetadata());
+      return;
+    }
+
     gfx::Size view_size_in_pixels =
         rwhv->GetNativeView()->GetPhysicalBackingSize();
     if (view_size_in_pixels.IsEmpty()) {
       std::move(result_callback).Run(viz::CopyOutputBitmapWithMetadata());
       return;
     }
+
     gfx::Rect source_rect = gfx::Rect(view_size_in_pixels);
     gfx::Size thumbnail_size(
         gfx::ScaleToCeiledSize(view_size_in_pixels, thumbnail_scale_));
@@ -97,6 +116,7 @@
 
   void OnFinishGetTabThumbnailBitmap(
       const content::CopyFromSurfaceResult& result) {
+    decrementor_.RunAndReset();
     if (!result.has_value() || drop_after_readback_) {
       std::move(end_callback_).Run(0.f, SkBitmap());
       return;
@@ -113,6 +133,7 @@
   const float thumbnail_scale_;
   TabReadbackCallback end_callback_;
   bool drop_after_readback_{false};
+  base::ScopedClosureRunner decrementor_;
 
   base::WeakPtrFactory<TabReadbackRequest> weak_factory_{this};
 };
@@ -202,31 +223,6 @@
   }
 }
 
-content::RenderWidgetHostView* TabContentManager::GetRwhvForTab(
-    TabAndroid* tab_android) {
-  DCHECK(tab_android);
-  const int tab_id = tab_android->GetAndroidId();
-  if (pending_tab_readbacks_.find(tab_id) != pending_tab_readbacks_.end()) {
-    return nullptr;
-  }
-
-  content::WebContents* web_contents = tab_android->web_contents();
-  DCHECK(web_contents);
-
-  content::RenderViewHost* rvh = web_contents->GetRenderViewHost();
-  if (!rvh) {
-    return nullptr;
-  }
-
-  content::RenderWidgetHost* rwh = rvh->GetWidget();
-  content::RenderWidgetHostView* rwhv = rwh ? rwh->GetView() : nullptr;
-  if (!rwhv || !rwhv->IsSurfaceAvailableForCopy()) {
-    return nullptr;
-  }
-
-  return rwhv;
-}
-
 TabContentManager::ThumbnailCaptureTrackerPtr TabContentManager::TrackCapture(
     thumbnail::TabId tab_id) {
   CleanupTrackers();
@@ -270,16 +266,14 @@
   DCHECK(tab_android);
   const int tab_id = tab_android->GetAndroidId();
 
-  content::RenderWidgetHostView* rwhv = GetRwhvForTab(tab_android);
-  // If the tab's ID is in the list of VisibleIds then it has a LayoutTab
-  // active and can be captured. Otherwise the surface will be missing and
-  // the capture will stall forever.
-  if (!rwhv || !thumbnail_cache_.IsInVisibleIds(tab_id)) {
+  content::WebContents* web_contents = tab_android->GetContents();
+  if (!web_contents) {
     if (j_callback) {
       RunObjectCallbackAndroid(j_callback, nullptr);
     }
     return;
   }
+
   if (!thumbnail_cache_.CheckAndUpdateThumbnailMetaData(
           tab_id, tab_android->GetURL(), /*force_update=*/false)) {
     return;
@@ -292,7 +286,7 @@
                                     ScopedJavaGlobalRef<jobject>(j_callback)),
                      return_bitmap);
   pending_tab_readbacks_[tab_id] = std::make_unique<TabReadbackRequest>(
-      rwhv, thumbnail_scale, std::move(readback_done_callback));
+      web_contents, thumbnail_scale, std::move(readback_done_callback));
 }
 
 void TabContentManager::CacheTabWithBitmap(JNIEnv* env,
diff --git a/chrome/browser/android/compositor/tab_content_manager.h b/chrome/browser/android/compositor/tab_content_manager.h
index bf984d3..1b26210 100644
--- a/chrome/browser/android/compositor/tab_content_manager.h
+++ b/chrome/browser/android/compositor/tab_content_manager.h
@@ -73,12 +73,12 @@
                         int primary_tab_id);
 
   void CaptureThumbnail(JNIEnv* env,
-                        TabAndroid* tab_android,
+                        TabAndroid* tab,
                         float thumbnail_scale,
                         bool return_bitmap,
                         const base::android::JavaRef<jobject>& j_callback);
   void CacheTabWithBitmap(JNIEnv* env,
-                          TabAndroid* tab_android,
+                          TabAndroid* tab,
                           const base::android::JavaRef<jobject>& bitmap,
                           float thumbnail_scale);
   void InvalidateIfChanged(JNIEnv* env, int32_t tab_id, const GURL& url);
@@ -115,7 +115,6 @@
   using JavaBitmapCallback =
       base::OnceCallback<void(const base::android::JavaRef<jobject>&)>;
 
-  content::RenderWidgetHostView* GetRwhvForTab(TabAndroid* tab_android);
   ThumbnailCaptureTrackerPtr TrackCapture(thumbnail::TabId tab_id);
   void CleanupTrackers();
   void OnTrackingFinished(int tab_id,
diff --git a/chrome/browser/android/omnibox/composebox_query_controller_bridge.cc b/chrome/browser/android/omnibox/composebox_query_controller_bridge.cc
index 55fa3911..b7646a38 100644
--- a/chrome/browser/android/omnibox/composebox_query_controller_bridge.cc
+++ b/chrome/browser/android/omnibox/composebox_query_controller_bridge.cc
@@ -142,7 +142,10 @@
 }
 
 size_t ComposeboxQueryControllerBridge::GetAttachmentCount() const {
-  return query_controller()->GetFileInfoList().size();
+  // Uploaded context tokens are updated as soon as
+  // session_handle_->CreateContextToken() is called in the file or tab context
+  // upload flows.
+  return session_handle_->GetUploadedContextTokens().size();
 }
 
 base::WeakPtr<ComposeboxQueryControllerBridge>
@@ -255,16 +258,6 @@
   search_url_request_info->query_start_time = base::Time::Now();
   search_url_request_info->aim_entry_point =
       omnibox::ANDROID_CHROME_FUSEBOX_ENTRY_POINT;
-  search_url_request_info->invocation_source =
-      lens::LensOverlayInvocationSource::kOmniboxContextualQuery;
-  // Read the list of tokens from the fileinfo map in the contextual search
-  // controller.
-  // TODO(crbug.com/455952553): Rely on the contextual search session handle
-  // to track uploaded context tokens.
-  for (const contextual_search::FileInfo* file_info :
-       query_controller()->GetFileInfoList()) {
-    search_url_request_info->file_tokens.push_back(file_info->file_token);
-  }
   return search_url_request_info;
 }
 
@@ -274,7 +267,7 @@
     const base::android::JavaRef<jobject>& j_callback) {
   auto search_url_request_info =
       CreateSearchUrlRequestInfoFromUrl(std::move(url));
-  query_controller()->CreateSearchUrl(
+  session_handle_->CreateSearchUrl(
       std::move(search_url_request_info),
       base::BindOnce(&RunJavaCallback,
                      base::android::ScopedJavaGlobalRef<jobject>(j_callback)));
@@ -287,7 +280,7 @@
   auto search_url_request_info =
       CreateSearchUrlRequestInfoFromUrl(std::move(url));
   search_url_request_info->additional_params["imgn"] = "1";
-  query_controller()->CreateSearchUrl(
+  session_handle_->CreateSearchUrl(
       std::move(search_url_request_info),
       base::BindOnce(&RunJavaCallback,
                      base::android::ScopedJavaGlobalRef<jobject>(j_callback)));
@@ -333,16 +326,13 @@
 
 std::unique_ptr<lens::proto::LensOverlaySuggestInputs>
 ComposeboxQueryControllerBridge::CreateLensOverlaySuggestInputs() const {
-  auto tokens = std::vector<base::UnguessableToken>();
-  // Read the list of tokens from the fileinfo list in the contextual search
-  // controller.
-  // TODO(crbug.com/455843962): Rely on the contextual search session handle
-  // to track uploaded context tokens.
-  for (const contextual_search::FileInfo* file_info :
-       query_controller()->GetFileInfoList()) {
-    tokens.push_back(file_info->file_token);
+  std::optional<lens::proto::LensOverlaySuggestInputs> suggest_inputs =
+      session_handle_->GetSuggestInputs();
+  if (!suggest_inputs.has_value()) {
+    return std::make_unique<lens::proto::LensOverlaySuggestInputs>();
   }
-  return query_controller()->CreateSuggestInputs(tokens);
+  return std::make_unique<lens::proto::LensOverlaySuggestInputs>(
+      *suggest_inputs);
 }
 
 void ComposeboxQueryControllerBridge::OnFileUploadStatusChanged(
diff --git a/chrome/browser/ash/login/login_integration_test.cc b/chrome/browser/ash/login/login_integration_test.cc
index 03e0373..dc14a2e 100644
--- a/chrome/browser/ash/login/login_integration_test.cc
+++ b/chrome/browser/ash/login/login_integration_test.cc
@@ -52,7 +52,8 @@
   ~GaiaLoginIntegrationTest() override = default;
 };
 
-IN_PROC_BROWSER_TEST_F(GaiaLoginIntegrationTest, GaiaLogin) {
+// TODO: b/484110852 - Re-enable this test once the flakiness is fixed.
+IN_PROC_BROWSER_TEST_F(GaiaLoginIntegrationTest, DISABLED_GaiaLogin) {
   login_mixin().Login();
 
   // Waits for the primary user session to start.
diff --git a/chrome/browser/ash/nearby/nearby_dependencies_provider.cc b/chrome/browser/ash/nearby/nearby_dependencies_provider.cc
index 222f1295..ac127fe9 100644
--- a/chrome/browser/ash/nearby/nearby_dependencies_provider.cc
+++ b/chrome/browser/ash/nearby/nearby_dependencies_provider.cc
@@ -294,18 +294,14 @@
       std::move(tcp_socket_factory.receiver));
 
   MojoPipe<::sharing::mojom::MdnsManager> mdns_manager;
-  if (::features::IsNearbyMdnsEnabled()) {
-    mojo::MakeSelfOwnedReceiver(
-        std::make_unique<::nearby::sharing::NearbyConnectionsMdnsManager>(),
-        std::move(mdns_manager.receiver));
-  }
+  mojo::MakeSelfOwnedReceiver(
+      std::make_unique<::nearby::sharing::NearbyConnectionsMdnsManager>(),
+      std::move(mdns_manager.receiver));
 
   return ::sharing::mojom::WifiLanDependencies::New(
       std::move(cros_network_config.remote),
       std::move(firewall_hole_factory.remote),
-      std::move(tcp_socket_factory.remote),
-      (::features::IsNearbyMdnsEnabled() ? std::move(mdns_manager.remote)
-                                         : mojo::NullRemote()));
+      std::move(tcp_socket_factory.remote), std::move(mdns_manager.remote));
 }
 
 sharing::mojom::WifiDirectDependenciesPtr
diff --git a/chrome/browser/autofill/android/junit/src/org/chromium/chrome/browser/autofill/editors/autofill_ai/EntityEditorModuleTest.java b/chrome/browser/autofill/android/junit/src/org/chromium/chrome/browser/autofill/editors/autofill_ai/EntityEditorModuleTest.java
index 5e2b41f..1225e26 100644
--- a/chrome/browser/autofill/android/junit/src/org/chromium/chrome/browser/autofill/editors/autofill_ai/EntityEditorModuleTest.java
+++ b/chrome/browser/autofill/android/junit/src/org/chromium/chrome/browser/autofill/editors/autofill_ai/EntityEditorModuleTest.java
@@ -37,7 +37,6 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.mockito.quality.Strictness;
@@ -183,7 +182,6 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.openMocks(this);
 
         IdentityServicesProvider.setIdentityManagerForTesting(mIdentityManager);
         when(mAutofillProfileBridgeJni.getSupportedCountries()).thenReturn(mSupportedCountries);
diff --git a/chrome/browser/background/glic/glic_status_icon.cc b/chrome/browser/background/glic/glic_status_icon.cc
index 2409a9c..21b948b0 100644
--- a/chrome/browser/background/glic/glic_status_icon.cc
+++ b/chrome/browser/background/glic/glic_status_icon.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/glic/glic_profile_manager.h"
 #include "chrome/browser/glic/glic_settings_util.h"
 #include "chrome/browser/glic/host/glic.mojom.h"
+#include "chrome/browser/glic/public/features.h"
 #include "chrome/browser/glic/public/glic_keyed_service_factory.h"
 #include "chrome/browser/glic/resources/glic_resources.h"
 #include "chrome/browser/glic/resources/grit/glic_browser_resources.h"
@@ -42,6 +43,10 @@
 #include "ui/native_theme/native_theme.h"
 #include "ui/views/widget/widget.h"
 
+#if BUILDFLAG(IS_MAC)
+#include "components/omnibox/browser/vector_icons.h"  // nogncheck
+#endif                                                // BUILDFLAG(IS_MAC)
+
 #if BUILDFLAG(IS_WIN)
 #include "chrome/browser/background/glic/glic_status_icon_win.h"
 #endif  // BUILDFLAG(IS_WIN)
@@ -334,6 +339,12 @@
   // On Mac and Linux, theming is handled by the system,. whereas ChromeOS and
   // Win need theme aware icons. (See GetIcon() implementations of
   // GlicStatusIconWin and GlicStatusIconChromeOS)
+#if BUILDFLAG(IS_MAC)
+  if (base::FeatureList::IsEnabled(features::kGlicChromeStatusIcon)) {
+    return gfx::CreateVectorIcon(omnibox::kProductChromeRefreshIcon,
+                                 SK_ColorWHITE);
+  }
+#endif
   const auto& icon =
       glic::GlicVectorIconManager::GetVectorIcon(IDR_GLIC_STATUS_ICON);
   return gfx::CreateVectorIcon(icon, SK_ColorWHITE);
diff --git a/chrome/browser/chrome_browser_interface_binders_webui_parts_chromeos.cc b/chrome/browser/chrome_browser_interface_binders_webui_parts_chromeos.cc
index 979f06e..e57c9b4 100644
--- a/chrome/browser/chrome_browser_interface_binders_webui_parts_chromeos.cc
+++ b/chrome/browser/chrome_browser_interface_binders_webui_parts_chromeos.cc
@@ -607,7 +607,6 @@
   registry.ForWebUI<ash::file_manager::FileManagerUI>();
   registry.ForWebUI<ash::smb_dialog::SmbShareDialogUI>();
   registry.ForWebUI<ash::smb_dialog::SmbCredentialsDialogUI>();
-  registry.ForWebUI<FeedbackUI>();
   registry.ForWebUI<ash::MallUI>().Add<ash::mall::mojom::PageHandler>();
 
 #if !defined(OFFICIAL_BUILD)
diff --git a/chrome/browser/chrome_browser_interface_binders_webui_parts_desktop.cc b/chrome/browser/chrome_browser_interface_binders_webui_parts_desktop.cc
index ccb5481..2f4e432 100644
--- a/chrome/browser/chrome_browser_interface_binders_webui_parts_desktop.cc
+++ b/chrome/browser/chrome_browser_interface_binders_webui_parts_desktop.cc
@@ -203,6 +203,10 @@
 #include "components/surface_embed/common/surface_embed.mojom.h"
 #endif
 
+#if BUILDFLAG(ENABLE_GLIC)
+#include "chrome/browser/glic/selection/selection_overlay_untrusted_ui.h"
+#endif
+
 namespace chrome::internal {
 
 using content::RegisterWebUIControllerInterfaceBinder;
@@ -710,6 +714,13 @@
   registry.ForWebUI<NtpMicrosoftAuthUntrustedUI>()
       .Add<new_tab_page::mojom::
                MicrosoftAuthUntrustedDocumentInterfacesFactory>();
+
+#if BUILDFLAG(ENABLE_GLIC)
+  if (base::FeatureList::IsEnabled(features::kGlicRegionSelectionNew)) {
+    registry.ForWebUI<glic::SelectionOverlayUntrustedUI>()
+        .Add<glic::selection::SelectionOverlayPageHandlerFactory>();
+  }
+#endif
 }
 
 }  // namespace chrome::internal
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager_unittest.cc b/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager_unittest.cc
index fedb653..f977549 100644
--- a/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager_unittest.cc
+++ b/chrome/browser/chromeos/extensions/telemetry/api/events/event_manager_unittest.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/chromeos/extensions/telemetry/api/events/fake_events_service_factory.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
 #include "chrome/browser/ui/tabs/tab_enums.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.h"
@@ -130,6 +131,20 @@
     }
   }
 
+  // TODO(crbug.com/480103891): We should not be faking browser activation state
+  // via indirect means (such as direct calls to `DidBecomeActive()`). We should
+  // instead convert this to an interactive browser test and directly activate
+  // the browser's backing ui::BaseWindow.
+  void ActivateBrowser(BrowserWindowInterface* browser) {
+    // We must fake deactivation the previously activated browser first.
+    GetLastActiveBrowserWindowInterfaceWithAnyProfile()
+        ->GetBrowserForMigrationOnly()
+        ->DidBecomeInactive();
+
+    // Simulate activation of `browser`.
+    browser->GetBrowserForMigrationOnly()->DidBecomeActive();
+  }
+
   EventManager* event_manager() { return EventManager::Get(profile()); }
 
   base::flat_map<extensions::ExtensionId, std::unique_ptr<AppUiObserver>>&
@@ -209,7 +224,7 @@
                                           /*cert_status=*/net::OK);
   auto new_browser =
       CreateBrowser(GetProfile(), Browser::Type::TYPE_NORMAL, false);
-  BrowserList::SetLastActive(new_browser.get());
+  ActivateBrowser(new_browser.get());
 
   EXPECT_EQ(
       EventManager::kSuccess,
@@ -258,7 +273,7 @@
                                           /*cert_status=*/net::OK);
   auto new_browser =
       CreateBrowser(GetProfile(), Browser::Type::TYPE_NORMAL, false);
-  BrowserList::SetLastActive(new_browser.get());
+  ActivateBrowser(new_browser.get());
 
   EXPECT_EQ(EventManager::kAppUiNotFocused,
             event_manager()->RegisterExtensionForEvent(
diff --git a/chrome/browser/contextual_tasks/contextual_tasks_ui.cc b/chrome/browser/contextual_tasks/contextual_tasks_ui.cc
index 8441491..40799de3 100644
--- a/chrome/browser/contextual_tasks/contextual_tasks_ui.cc
+++ b/chrome/browser/contextual_tasks/contextual_tasks_ui.cc
@@ -203,7 +203,9 @@
 }
 
 ContextualTasksUI::ContextualTasksUI(content::WebUI* web_ui)
-    : ui::MojoWebUIController(web_ui),
+    : ui::MojoWebUIController(web_ui,
+                              /*enable_chrome_send=*/false,
+                              /*enable_chrome_histograms=*/true),
       ui_service_(contextual_tasks::ContextualTasksUiServiceFactory::
                       GetForBrowserContext(
                           web_ui->GetWebContents()->GetBrowserContext())),
diff --git a/chrome/browser/devtools/inspector_protocol_config.json b/chrome/browser/devtools/inspector_protocol_config.json
index 84e3636..6712a74 100644
--- a/chrome/browser/devtools/inspector_protocol_config.json
+++ b/chrome/browser/devtools/inspector_protocol_config.json
@@ -35,7 +35,7 @@
             },
             {
                 "domain": "Extensions",
-                "include": [ "triggerAction", "loadUnpacked", "getStorageItems", "setStorageItems", "removeStorageItems", "clearStorageItems", "uninstall" ],
+                "include": [ "triggerAction", "loadUnpacked", "getStorageItems", "setStorageItems", "removeStorageItems", "clearStorageItems", "uninstall", "getExtensions" ],
                 "async": [ "loadUnpacked", "getStorageItems", "setStorageItems", "removeStorageItems", "clearStorageItems", "uninstall" ]
             },
             {
diff --git a/chrome/browser/devtools/protocol/devtools_extensions_browsertest.cc b/chrome/browser/devtools/protocol/devtools_extensions_browsertest.cc
index 159c9e2d..b4900f5 100644
--- a/chrome/browser/devtools/protocol/devtools_extensions_browsertest.cc
+++ b/chrome/browser/devtools/protocol/devtools_extensions_browsertest.cc
@@ -5,6 +5,7 @@
 #include "base/features.h"
 #include "base/files/file.h"
 #include "base/path_service.h"
+#include "base/test/values_test_util.h"
 #include "base/values.h"
 #include "chrome/browser/devtools/protocol/devtools_protocol_test_support.h"
 #include "chrome/browser/extensions/browser_window_util.h"
@@ -512,6 +513,56 @@
 }
 
 IN_PROC_BROWSER_TEST_F(DevToolsExtensionsProtocolWithUnsafeDebuggingTest,
+                       CanGetExtensions) {
+  base::FilePath extensions_dir =
+      base::PathService::CheckedGet(chrome::DIR_TEST_DATA)
+          .AppendASCII("devtools")
+          .AppendASCII("extensions");
+
+  base::FilePath unpacked_path =
+      extensions_dir.AppendASCII("simple_background_page");
+  base::FilePath packed_path = extensions_dir.AppendASCII("service_worker");
+
+  // Load an unpacked extension.
+  const base::DictValue* result =
+      SendLoadUnpackedCommand("simple_background_page");
+  std::string id = *result->FindString("id");
+  ASSERT_FALSE(id.empty());
+
+  // Load packed extension
+  extensions::ChromeTestExtensionLoader loader(browser()->profile());
+  loader.set_location(extensions::mojom::ManifestLocation::kInternal);
+  loader.set_pack_extension(true);
+  auto packed_extension = loader.LoadExtension(packed_path);
+  ASSERT_TRUE(packed_extension);
+  std::string packed_id = packed_extension->id();
+  ASSERT_FALSE(packed_id.empty());
+
+  // Verify the internal extension is actually in the registry.
+  extensions::ExtensionRegistry* registry =
+      extensions::ExtensionRegistry::Get(browser()->profile());
+  ASSERT_TRUE(registry->enabled_extensions().Contains(packed_id));
+
+  content::RunAllTasksUntilIdle();
+  const base::DictValue* list_result =
+      SendCommandSync("Extensions.getExtensions", base::DictValue());
+  ASSERT_TRUE(list_result);
+
+  const base::ListValue* extensions = list_result->FindList("extensions");
+  ASSERT_TRUE(extensions);
+  EXPECT_EQ(extensions->size(), 1u);
+
+  const base::DictValue& extension_info = (*extensions)[0].GetDict();
+  EXPECT_EQ(*extension_info.FindString("id"), id);
+  EXPECT_EQ(*extension_info.FindString("name"),
+            "Test Extension - Simple Background Page");
+  EXPECT_EQ(*extension_info.FindString("version"), "0.1");
+  EXPECT_TRUE(*extension_info.FindBool("enabled"));
+  EXPECT_EQ(*extension_info.FindStringByDottedPath("path"),
+            unpacked_path.AsUTF8Unsafe());
+}
+
+IN_PROC_BROWSER_TEST_F(DevToolsExtensionsProtocolWithUnsafeDebuggingTest,
                        TriggerActionShowsSidePanel) {
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank")));
   ExtensionTestMessageListener activated_listener("running");
diff --git a/chrome/browser/devtools/protocol/extensions_handler.cc b/chrome/browser/devtools/protocol/extensions_handler.cc
index d5e3dd95..313a8fd 100644
--- a/chrome/browser/devtools/protocol/extensions_handler.cc
+++ b/chrome/browser/devtools/protocol/extensions_handler.cc
@@ -11,6 +11,7 @@
 #include "base/functional/bind.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/devtools/chrome_devtools_manager_delegate.h"
+#include "chrome/browser/devtools/devtools_browser_context_manager.h"
 #include "chrome/browser/devtools/protocol/extensions.h"
 #include "chrome/browser/devtools/protocol/protocol.h"
 #include "chrome/browser/extensions/browser_window_util.h"
@@ -25,6 +26,7 @@
 #include "extensions/browser/api/storage/storage_utils.h"
 #include "extensions/browser/extension_registrar.h"
 #include "extensions/browser/unpacked_installer.h"
+#include "extensions/common/manifest.h"
 
 namespace {
 
@@ -246,6 +248,49 @@
       protocol::Response::InvalidRequest(base::UTF16ToUTF8(err)));
 }
 
+protocol::Response ExtensionsHandler::GetExtensions(
+    std::unique_ptr<protocol::Array<protocol::Extensions::ExtensionInfo>>*
+        out_result) {
+  if (!allow_loading_extensions_) {
+    return protocol::Response::ServerError("Method not available.");
+  }
+  content::BrowserContext* context =
+      DevToolsBrowserContextManager::GetInstance().GetDefaultBrowserContext();
+
+  if (!context) {
+    return protocol::Response::ServerError("Could not find browser context.");
+  }
+
+  extensions::ExtensionRegistry* registry =
+      extensions::ExtensionRegistry::Get(context);
+  if (!registry) {
+    return protocol::Response::ServerError(
+        "Could not find extension registry.");
+  }
+
+  auto result =
+      std::make_unique<protocol::Array<protocol::Extensions::ExtensionInfo>>();
+  extensions::ExtensionSet all_extensions =
+      registry->GenerateInstalledExtensionsSet();
+
+  for (const auto& extension : all_extensions) {
+    if (extensions::Manifest::IsUnpackedLocation(extension->location())) {
+      bool is_enabled =
+          registry->enabled_extensions().Contains(extension->id());
+      result->emplace_back(protocol::Extensions::ExtensionInfo::Create()
+                               .SetId(extension->id())
+                               .SetName(extension->name())
+                               .SetVersion(extension->VersionString())
+                               .SetEnabled(is_enabled)
+                               .SetPath(extension->path().AsUTF8Unsafe())
+                               .Build());
+    }
+  }
+
+  *out_result = std::move(result);
+  return protocol::Response::Success();
+}
+
 void ExtensionsHandler::Uninstall(const protocol::String& id,
                                   std::unique_ptr<UninstallCallback> callback) {
   if (!allow_loading_extensions_) {
diff --git a/chrome/browser/devtools/protocol/extensions_handler.h b/chrome/browser/devtools/protocol/extensions_handler.h
index ead0836..e9bf529 100644
--- a/chrome/browser/devtools/protocol/extensions_handler.h
+++ b/chrome/browser/devtools/protocol/extensions_handler.h
@@ -34,6 +34,9 @@
                 const extensions::Extension* extension,
                 const base::FilePath&,
                 const std::u16string& err);
+  protocol::Response GetExtensions(
+      std::unique_ptr<protocol::Array<protocol::Extensions::ExtensionInfo>>*
+          out_result) override;
   void Uninstall(const protocol::String& id,
                  std::unique_ptr<UninstallCallback> callback) override;
   void OnUninstalled(std::unique_ptr<UninstallCallback> callback);
diff --git a/chrome/browser/downgrade/snapshot_file_collector.cc b/chrome/browser/downgrade/snapshot_file_collector.cc
index 792e27a..b8a7ff7 100644
--- a/chrome/browser/downgrade/snapshot_file_collector.cc
+++ b/chrome/browser/downgrade/snapshot_file_collector.cc
@@ -87,15 +87,6 @@
                           SnapshotItemDetails::ItemType::kFile,
                           chrome_browsing_data_remover::DATA_TYPE_BOOKMARKS),
       // Tab Restore and sessions
-      // TODO(crbug.com/40704630): Remove legacy snapshots in M89
-      SnapshotItemDetails(
-          base::FilePath(sessions::kLegacyCurrentTabSessionFileName),
-          SnapshotItemDetails::ItemType::kFile,
-          chrome_browsing_data_remover::DATA_TYPE_HISTORY),
-      SnapshotItemDetails(
-          base::FilePath(sessions::kLegacyCurrentSessionFileName),
-          SnapshotItemDetails::ItemType::kFile,
-          chrome_browsing_data_remover::DATA_TYPE_HISTORY),
       SnapshotItemDetails(base::FilePath(sessions::kSessionsDirectory),
                           SnapshotItemDetails::ItemType::kDirectory,
                           chrome_browsing_data_remover::DATA_TYPE_HISTORY),
diff --git a/chrome/browser/enterprise/connectors/analysis/local_binary_upload_service.cc b/chrome/browser/enterprise/connectors/analysis/local_binary_upload_service.cc
index 548e80c7..58960273 100644
--- a/chrome/browser/enterprise/connectors/analysis/local_binary_upload_service.cc
+++ b/chrome/browser/enterprise/connectors/analysis/local_binary_upload_service.cc
@@ -705,8 +705,8 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DVLOG(1) << __func__ << ": id=" << id;
 
-  if (active_requests_.count(id) > 0) {
-    const auto& info = active_requests_.at(id);
+  if (auto it = active_requests_.find(id); it != active_requests_.end()) {
+    const auto& info = it->second;
     RecordRequestMetrics(
         info, enterprise_connectors::ScanRequestUploadResult::kTimeout,
         ContentAnalysisResponse());
diff --git a/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc b/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
index fc38ff85..6777903 100644
--- a/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
+++ b/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
@@ -74,8 +74,9 @@
 }
 
 void ActivityLogAPI::OnListenerAdded(const EventListenerInfo& details) {
-  if (activity_log_->has_listeners())
+  if (activity_log_->has_listeners()) {
     return;
+  }
   StartOrStopListeningForExtensionActivities();
 }
 
@@ -138,8 +139,9 @@
   std::string page_url = filter.page_url ? *filter.page_url : std::string();
   std::string arg_url = filter.arg_url ? *filter.arg_url : std::string();
   int days_ago = -1;
-  if (filter.days_ago)
+  if (filter.days_ago) {
     days_ago = *filter.days_ago;
+  }
 
   // Call the ActivityLog.
   ActivityLog* activity_log = ActivityLog::GetInstance(browser_context());
@@ -157,8 +159,9 @@
     std::unique_ptr<std::vector<scoped_refptr<Action>>> activities) {
   // Convert Actions to ExtensionActivities.
   std::vector<ExtensionActivity> result_arr;
-  for (const auto& activity : *activities)
+  for (const auto& activity : *activities) {
     result_arr.push_back(activity->ConvertToExtensionActivity());
+  }
 
   // Populate the return object.
   ActivityResultSet result_set;
@@ -178,8 +181,9 @@
   std::vector<int64_t> action_ids;
   int64_t value;
   for (const auto& activity_id : params->activity_ids) {
-    if (base::StringToInt64(activity_id, &value))
+    if (base::StringToInt64(activity_id, &value)) {
       action_ids.push_back(value);
+    }
   }
 
   ActivityLog* activity_log = ActivityLog::GetInstance(browser_context());
@@ -219,8 +223,9 @@
   std::vector<GURL> gurls;
   const std::vector<std::string>& urls = params->urls;
   gurls.reserve(urls.size());
-  for (const std::string& url : urls)
+  for (const std::string& url : urls) {
     gurls.push_back(GURL(url));
+  }
 
   ActivityLog* activity_log = ActivityLog::GetInstance(browser_context());
   DCHECK(activity_log);
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_event_router.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_event_router.cc
index 0e260134..f0dd920 100644
--- a/chrome/browser/extensions/api/autofill_private/autofill_private_event_router.cc
+++ b/chrome/browser/extensions/api/autofill_private/autofill_private_event_router.cc
@@ -51,8 +51,9 @@
   // some unit tests try to create all context services, but don't initialize
   // the event router first.
   event_router_ = EventRouter::Get(context_);
-  if (!event_router_)
+  if (!event_router_) {
     return;
+  }
 
   personal_data_ =
       autofill::PersonalDataManagerFactory::GetForBrowserContext(context_);
@@ -132,8 +133,9 @@
 
 void AutofillPrivateEventRouter::BroadcastCurrentData() {
   // Ignore any updates before data is loaded. This can happen in tests.
-  if (!(personal_data_ && personal_data_->IsDataLoaded()))
+  if (!(personal_data_ && personal_data_->IsDataLoaded())) {
     return;
+  }
 
   autofill_util::AddressEntryList address_list =
       extensions::autofill_util::GenerateAddressList(
diff --git a/chrome/browser/extensions/api/automation/automation_apitest.cc b/chrome/browser/extensions/api/automation/automation_apitest.cc
index 44a7b11..e1da46ec 100644
--- a/chrome/browser/extensions/api/automation/automation_apitest.cc
+++ b/chrome/browser/extensions/api/automation/automation_apitest.cc
@@ -102,14 +102,16 @@
 var url = '';
 
 function findAutomationNode(root, condition) {
-  if (condition(root))
+  if (condition(root)) {
     return root;
+  }
 
   var children = root.children;
   for (var i = 0; i < children.length; i++) {
     var result = findAutomationNode(children[i], condition);
-    if (result)
+    if (result) {
       return result;
+    }
   }
   return null;
 }
@@ -848,21 +850,26 @@
   int automation_total_dur = 0;
   for (const base::Value& event : *trace_events) {
     const std::string* cat = event.GetDict().FindString("cat");
-    if (!cat || *cat != "accessibility")
+    if (!cat || *cat != "accessibility") {
       continue;
+    }
 
     const std::string* name = event.GetDict().FindString("name");
-    if (!name)
+    if (!name) {
       continue;
+    }
 
     std::optional<int> dur = event.GetDict().FindInt("dur");
-    if (!dur)
+    if (!dur) {
       continue;
+    }
 
-    if (*name == "AutomationAXTreeWrapper::OnAccessibilityEvents")
+    if (*name == "AutomationAXTreeWrapper::OnAccessibilityEvents") {
       automation_total_dur += *dur;
-    else if (*name == "RenderAccessibilityImpl::SendPendingAccessibilityEvents")
+    } else if (*name ==
+               "RenderAccessibilityImpl::SendPendingAccessibilityEvents") {
       renderer_total_dur += *dur;
+    }
   }
 
   ASSERT_GT(automation_total_dur, 0);
diff --git a/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.cc b/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.cc
index 608cf89f..2ec7401 100644
--- a/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.cc
+++ b/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.cc
@@ -43,8 +43,9 @@
     const Extension* extension,
     const AutomationInfo* automation_info,
     content::WebContents* contents) {
-  if (automation_info->desktop)
+  if (automation_info->desktop) {
     return true;
+  }
 
   const GURL& url = contents->GetURL();
 
@@ -60,8 +61,9 @@
   arc::ArcAccessibilityHelperBridge* bridge =
       arc::ArcAccessibilityHelperBridge::GetForBrowserContext(
           GetActiveUserContext());
-  if (bridge)
+  if (bridge) {
     return bridge->EnableTree(tree_id);
+  }
 #endif
   return false;
 }
diff --git a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
index cfda678..eb7f8ab4 100644
--- a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
+++ b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
@@ -114,8 +114,9 @@
 const BookmarkNode* GetNodeFromString(BookmarkModel* model,
                                       const std::string& id_string) {
   int64_t id;
-  if (!base::StringToInt64(id_string, &id))
+  if (!base::StringToInt64(id_string, &id)) {
     return nullptr;
+  }
   return bookmarks::GetBookmarkNodeByID(model, id);
 }
 
@@ -125,13 +126,15 @@
     BookmarkModel* model,
     const std::vector<std::string>& id_strings,
     std::vector<raw_ptr<const BookmarkNode, VectorExperimental>>* nodes) {
-  if (id_strings.empty())
+  if (id_strings.empty()) {
     return false;
+  }
 
   for (const auto& id_string : id_strings) {
     const BookmarkNode* node = GetNodeFromString(model, id_string);
-    if (!node)
+    if (!node) {
       return false;
+    }
     nodes->push_back(node);
   }
 
@@ -150,8 +153,9 @@
   element.id = base::NumberToString(node.id());
   element.parent_id = base::NumberToString(node.parent()->id());
 
-  if (node.is_url())
+  if (node.is_url()) {
     element.url = node.url().spec();
+  }
 
   element.title = base::UTF16ToUTF8(node.GetTitle());
   for (const auto& child : node.children()) {
@@ -169,8 +173,9 @@
     const BookmarkNodeData::Element& element) {
   bookmark_manager_private::BookmarkNodeDataElement node_element;
 
-  if (element.is_url)
+  if (element.is_url) {
     node_element.url = element.url.spec();
+  }
   node_element.title = base::UTF16ToUTF8(element.title);
   for (const auto& child : element.children) {
     node_element.children.push_back(CreateApiNodeDataElement(child));
@@ -198,8 +203,9 @@
     }
   } else {
     // We do not have a node IDs when the data comes from a different profile.
-    for (size_t i = 0; i < data.size(); ++i)
+    for (size_t i = 0; i < data.size(); ++i) {
       node_data.elements.push_back(CreateApiNodeDataElement(data.elements[i]));
+    }
   }
   return node_data;
 }
@@ -207,8 +213,9 @@
 bool HasPermanentNodes(
     const std::vector<raw_ptr<const BookmarkNode, VectorExperimental>>& list) {
   for (const BookmarkNode* node : list) {
-    if (node->is_permanent_node())
+    if (node->is_permanent_node()) {
       return true;
+    }
   }
   return false;
 }
@@ -242,8 +249,9 @@
 }
 
 BookmarkManagerPrivateEventRouter::~BookmarkManagerPrivateEventRouter() {
-  if (bookmark_model_)
+  if (bookmark_model_) {
     bookmark_model_->RemoveObserver(this);
+  }
 }
 
 void BookmarkManagerPrivateEventRouter::DispatchEvent(
@@ -318,8 +326,9 @@
     const std::string& event_name,
     base::ListValue args) {
   EventRouter* event_router = EventRouter::Get(profile_);
-  if (!event_router)
+  if (!event_router) {
     return;
+  }
 
   std::unique_ptr<Event> event(
       new Event(histogram_value, event_name, std::move(args)));
@@ -328,8 +337,9 @@
 
 void BookmarkManagerPrivateDragEventRouter::OnDragEnter(
     const BookmarkNodeData& data) {
-  if (!data.is_valid())
+  if (!data.is_valid()) {
     return;
+  }
   DispatchEvent(events::BOOKMARK_MANAGER_PRIVATE_ON_DRAG_ENTER,
                 bookmark_manager_private::OnDragEnter::kEventName,
                 bookmark_manager_private::OnDragEnter::Create(
@@ -344,8 +354,9 @@
 
 void BookmarkManagerPrivateDragEventRouter::OnDragLeave(
     const BookmarkNodeData& data) {
-  if (!data.is_valid())
+  if (!data.is_valid()) {
     return;
+  }
   DispatchEvent(events::BOOKMARK_MANAGER_PRIVATE_ON_DRAG_LEAVE,
                 bookmark_manager_private::OnDragLeave::kEventName,
                 bookmark_manager_private::OnDragLeave::Create(
@@ -354,8 +365,9 @@
 
 void BookmarkManagerPrivateDragEventRouter::OnDrop(
     const BookmarkNodeData& data) {
-  if (!data.is_valid())
+  if (!data.is_valid()) {
     return;
+  }
   DispatchEvent(events::BOOKMARK_MANAGER_PRIVATE_ON_DROP,
                 bookmark_manager_private::OnDrop::kEventName,
                 bookmark_manager_private::OnDrop::Create(
@@ -368,8 +380,9 @@
 
 const BookmarkNodeData*
 BookmarkManagerPrivateDragEventRouter::GetBookmarkNodeData() {
-  if (bookmark_drag_data_.is_valid())
+  if (bookmark_drag_data_.is_valid()) {
     return &bookmark_drag_data_;
+  }
   return nullptr;
 }
 
@@ -388,10 +401,12 @@
   }
 
   bookmarks::ManagedBookmarkService* managed = GetManagedBookmarkService();
-  if (cut && bookmarks::HasDescendantsOf(nodes, managed->managed_node()))
+  if (cut && bookmarks::HasDescendantsOf(nodes, managed->managed_node())) {
     return Error(bookmarks_errors::kModifyManagedError);
-  if (cut && HasPermanentNodes(nodes))
+  }
+  if (cut && HasPermanentNodes(nodes)) {
     return Error(bookmarks_errors::kModifySpecialError);
+  }
 
   if (cut) {
     BookmarkUIOperationsHelperNonMergedSurfaces::CutToClipboard(
@@ -408,54 +423,63 @@
 ExtensionFunction::ResponseValue
 BookmarkManagerPrivateCopyFunction::RunOnReady() {
   std::optional<Copy::Params> params = Copy::Params::Create(args());
-  if (!params)
+  if (!params) {
     return BadMessage();
+  }
   return CopyOrCut(false, params->id_list);
 }
 
 ExtensionFunction::ResponseValue
 BookmarkManagerPrivateCutFunction::RunOnReady() {
-  if (!EditBookmarksEnabled())
+  if (!EditBookmarksEnabled()) {
     return Error(bookmarks_errors::kEditBookmarksDisabled);
+  }
 
   std::optional<Cut::Params> params = Cut::Params::Create(args());
-  if (!params)
+  if (!params) {
     return BadMessage();
+  }
   return CopyOrCut(true, params->id_list);
 }
 
 ExtensionFunction::ResponseValue
 BookmarkManagerPrivatePasteFunction::RunOnReady() {
-  if (!EditBookmarksEnabled())
+  if (!EditBookmarksEnabled()) {
     return Error(bookmarks_errors::kEditBookmarksDisabled);
+  }
 
   std::optional<Paste::Params> params = Paste::Params::Create(args());
-  if (!params)
+  if (!params) {
     return BadMessage();
+  }
   BookmarkModel* model =
       BookmarkModelFactory::GetForBrowserContext(GetProfile());
   const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
   std::string error;
-  if (!CanBeModified(parent_node, &error))
+  if (!CanBeModified(parent_node, &error)) {
     return Error(error);
+  }
   BookmarkUIOperationsHelperNonMergedSurfaces helper(model, parent_node);
   bool can_paste = helper.CanPasteFromClipboard();
-  if (!can_paste)
+  if (!can_paste) {
     return Error("Could not paste from clipboard");
+  }
 
   // We want to use the highest index of the selected nodes as a destination.
   std::vector<raw_ptr<const BookmarkNode, VectorExperimental>> nodes;
   // No need to test return value, if we got an empty list, we insert at end.
-  if (params->selected_id_list)
+  if (params->selected_id_list) {
     GetNodesFromVector(model, *params->selected_id_list, &nodes);
+  }
   size_t highest_index = 0;
   for (const BookmarkNode* node : nodes) {
     // + 1 so that we insert after the selection.
     highest_index =
         std::max(highest_index, parent_node->GetIndexOf(node).value() + 1);
   }
-  if (!highest_index)
+  if (!highest_index) {
     highest_index = parent_node->children().size();
+  }
 
   helper.PasteFromClipboard(highest_index);
   return NoArguments();
@@ -464,18 +488,21 @@
 ExtensionFunction::ResponseValue
 BookmarkManagerPrivateCanPasteFunction::RunOnReady() {
   std::optional<CanPaste::Params> params = CanPaste::Params::Create(args());
-  if (!params)
+  if (!params) {
     return BadMessage();
+  }
 
   PrefService* prefs = user_prefs::UserPrefs::Get(GetProfile());
-  if (!prefs->GetBoolean(bookmarks::prefs::kEditBookmarksEnabled))
+  if (!prefs->GetBoolean(bookmarks::prefs::kEditBookmarksEnabled)) {
     return WithArguments(false);
+  }
 
   BookmarkModel* model =
       BookmarkModelFactory::GetForBrowserContext(GetProfile());
   const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
-  if (!parent_node)
+  if (!parent_node) {
     return Error(bookmarks_errors::kNoParentError);
+  }
   bool can_paste =
       BookmarkUIOperationsHelperNonMergedSurfaces(model, parent_node)
           .CanPasteFromClipboard();
@@ -502,33 +529,38 @@
 
 ExtensionFunction::ResponseValue
 BookmarkManagerPrivateSortChildrenFunction::RunOnReady() {
-  if (!EditBookmarksEnabled())
+  if (!EditBookmarksEnabled()) {
     return Error(bookmarks_errors::kEditBookmarksDisabled);
+  }
 
   std::optional<SortChildren::Params> params =
       SortChildren::Params::Create(args());
-  if (!params)
+  if (!params) {
     return BadMessage();
+  }
 
   BookmarkModel* model =
       BookmarkModelFactory::GetForBrowserContext(GetProfile());
   const BookmarkNode* parent_node = GetNodeFromString(model, params->parent_id);
   std::string error;
-  if (!CanBeModified(parent_node, &error))
+  if (!CanBeModified(parent_node, &error)) {
     return Error(error);
+  }
   model->SortChildren(parent_node);
   return NoArguments();
 }
 
 ExtensionFunction::ResponseValue
 BookmarkManagerPrivateStartDragFunction::RunOnReady() {
-  if (!EditBookmarksEnabled())
+  if (!EditBookmarksEnabled()) {
     return Error(bookmarks_errors::kEditBookmarksDisabled);
+  }
 
   content::WebContents* web_contents = GetSenderWebContents();
   std::optional<StartDrag::Params> params = StartDrag::Params::Create(args());
-  if (!params)
+  if (!params) {
     return BadMessage();
+  }
 
   BookmarkModel* model =
       BookmarkModelFactory::GetForBrowserContext(GetProfile());
@@ -539,8 +571,9 @@
   }
 
   ui::mojom::DragEventSource source = ui::mojom::DragEventSource::kMouse;
-  if (params->is_from_touch)
+  if (params->is_from_touch) {
     source = ui::mojom::DragEventSource::kTouch;
+  }
 
   chrome::DragBookmarks(
       GetProfile(), {std::move(nodes), params->drag_node_index, web_contents,
@@ -551,20 +584,23 @@
 
 ExtensionFunction::ResponseValue
 BookmarkManagerPrivateDropFunction::RunOnReady() {
-  if (!EditBookmarksEnabled())
+  if (!EditBookmarksEnabled()) {
     return Error(bookmarks_errors::kEditBookmarksDisabled);
+  }
 
   std::optional<Drop::Params> params = Drop::Params::Create(args());
-  if (!params)
+  if (!params) {
     return BadMessage();
+  }
 
   BookmarkModel* model =
       BookmarkModelFactory::GetForBrowserContext(GetProfile());
 
   const BookmarkNode* drop_parent = GetNodeFromString(model, params->parent_id);
   std::string error;
-  if (!CanBeModified(drop_parent, &error))
+  if (!CanBeModified(drop_parent, &error)) {
     return Error(error);
+  }
 
   content::WebContents* web_contents = GetSenderWebContents();
   size_t drop_index;
@@ -592,8 +628,9 @@
 ExtensionFunction::ResponseValue
 BookmarkManagerPrivateGetSubtreeFunction::RunOnReady() {
   std::optional<GetSubtree::Params> params = GetSubtree::Params::Create(args());
-  if (!params)
+  if (!params) {
     return BadMessage();
+  }
 
   const BookmarkNode* node = nullptr;
 
@@ -604,8 +641,9 @@
   } else {
     std::string error;
     node = GetBookmarkNodeFromId(params->id, &error);
-    if (!node)
+    if (!node) {
       return Error(error);
+    }
   }
 
   std::vector<api::bookmarks::BookmarkTreeNode> nodes;
@@ -622,13 +660,15 @@
 
 ExtensionFunction::ResponseValue
 BookmarkManagerPrivateRemoveTreesFunction::RunOnReady() {
-  if (!EditBookmarksEnabled())
+  if (!EditBookmarksEnabled()) {
     return Error(bookmarks_errors::kEditBookmarksDisabled);
+  }
 
   std::optional<RemoveTrees::Params> params =
       RemoveTrees::Params::Create(args());
-  if (!params)
+  if (!params) {
     return BadMessage();
+  }
 
   BookmarkModel* model = GetBookmarkModel();
   bookmarks::ManagedBookmarkService* managed = GetManagedBookmarkService();
@@ -636,8 +676,9 @@
   int64_t id;
   std::string error;
   for (const std::string& id_string : params->id_list) {
-    if (!base::StringToInt64(id_string, &id))
+    if (!base::StringToInt64(id_string, &id)) {
       return Error(bookmarks_errors::kInvalidIdError);
+    }
     if (!bookmarks_helpers::RemoveNode(model, managed, id, true, &error)) {
       return Error(error);
     }
@@ -648,8 +689,9 @@
 
 ExtensionFunction::ResponseValue
 BookmarkManagerPrivateUndoFunction::RunOnReady() {
-  if (!EditBookmarksEnabled())
+  if (!EditBookmarksEnabled()) {
     return Error(bookmarks_errors::kEditBookmarksDisabled);
+  }
 
   BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()->
       Undo();
@@ -658,8 +700,9 @@
 
 ExtensionFunction::ResponseValue
 BookmarkManagerPrivateRedoFunction::RunOnReady() {
-  if (!EditBookmarksEnabled())
+  if (!EditBookmarksEnabled()) {
     return Error(bookmarks_errors::kEditBookmarksDisabled);
+  }
 
   BookmarkUndoServiceFactory::GetForProfile(GetProfile())->undo_manager()->
       Redo();
@@ -670,15 +713,18 @@
 BookmarkManagerPrivateOpenInNewTabFunction::RunOnReady() {
   std::optional<OpenInNewTab::Params> params =
       OpenInNewTab::Params::Create(args());
-  if (!params)
+  if (!params) {
     return BadMessage();
+  }
 
   std::string error;
   const BookmarkNode* node = GetBookmarkNodeFromId(params->id, &error);
-  if (!node)
+  if (!node) {
     return Error(error);
-  if (!node->is_url())
+  }
+  if (!node->is_url()) {
     return Error("Cannot open a folder in a new tab.");
+  }
 
   OpenTabHelper::Params options;
   if (params->params) {
@@ -704,8 +750,9 @@
   base::expected<content::WebContents*, std::string> result =
       OpenTabHelper::OpenTab(validated_url, *maybe_browser.value(), *this,
                              options);
-  if (!result.has_value())
+  if (!result.has_value()) {
     return Error(result.error());
+  }
 
   content::WebContents* new_contents = result.value();
 
@@ -729,8 +776,9 @@
 BookmarkManagerPrivateOpenInNewWindowFunction::RunOnReady() {
   std::optional<OpenInNewWindow::Params> params =
       OpenInNewWindow::Params::Create(args());
-  if (!params)
+  if (!params) {
     return BadMessage();
+  }
 
   Profile* calling_profile = Profile::FromBrowserContext(browser_context());
 
@@ -745,8 +793,9 @@
   std::vector<GURL> urls;
   urls.reserve(nodes.size());
   for (const bookmarks::BookmarkNode* node : nodes) {
-    if (!node->is_url())
+    if (!node->is_url()) {
       return Error("Cannot open a folder in a new window.");
+    }
     urls.push_back(node->url());
   }
 
@@ -754,8 +803,9 @@
   windows_util::IncognitoResult incognito_result =
       windows_util::ShouldOpenIncognitoWindow(calling_profile,
                                               params->incognito, &urls, &error);
-  if (incognito_result == windows_util::IncognitoResult::kError)
+  if (incognito_result == windows_util::IncognitoResult::kError) {
     return Error(std::move(error));
+  }
 
   std::vector<UrlAndId> url_and_ids;
   urls.reserve(nodes.size());
@@ -784,8 +834,9 @@
     navigate_params.disposition =
         first_tab ? WindowOpenDisposition::NEW_WINDOW
                   : WindowOpenDisposition::NEW_FOREGROUND_TAB;
-    if (params->incognito)
+    if (params->incognito) {
       navigate_params.disposition = WindowOpenDisposition::OFF_THE_RECORD;
+    }
     base::WeakPtr<content::NavigationHandle> handle =
         Navigate(&navigate_params);
     if (handle) {
@@ -839,8 +890,9 @@
 BookmarkManagerPrivateIOFunction::~BookmarkManagerPrivateIOFunction() {
   // There may be pending file dialogs, we need to tell them that we've gone
   // away so they don't try and call back to us.
-  if (select_file_dialog_.get())
+  if (select_file_dialog_.get()) {
     select_file_dialog_->ListenerDestroyed();
+  }
 }
 
 void BookmarkManagerPrivateIOFunction::FileSelectionCanceled() {
@@ -850,12 +902,14 @@
 void BookmarkManagerPrivateIOFunction::ShowSelectFileDialog(
     ui::SelectFileDialog::Type type,
     const base::FilePath& default_path) {
-  if (!dispatcher())
+  if (!dispatcher()) {
     return;  // Extension was unloaded.
+  }
 
   // Early return if the select file dialog is already active.
-  if (select_file_dialog_)
+  if (select_file_dialog_) {
     return;
+  }
 
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
@@ -891,8 +945,9 @@
 
 ExtensionFunction::ResponseValue
 BookmarkManagerPrivateImportFunction::RunOnReady() {
-  if (!EditBookmarksEnabled())
+  if (!EditBookmarksEnabled()) {
     return Error(bookmarks_errors::kEditBookmarksDisabled);
+  }
   ShowSelectFileDialog(ui::SelectFileDialog::SELECT_OPEN_FILE,
                        base::FilePath());
   // TODO(crbug.com/40127463): This will respond before a file is selected,
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
index 31760c5..ccf3cdd 100644
--- a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
+++ b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
@@ -73,8 +73,9 @@
 
 void BrailleControllerImpl::TryLoadLibBrlApi() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (skip_libbrlapi_so_load_ || libbrlapi_loader_.loaded())
+  if (skip_libbrlapi_so_load_ || libbrlapi_loader_.loaded()) {
     return;
+  }
 
   // This api version needs to match the one contained in
   // third_party/libbrlapi/brlapi.h.
@@ -129,8 +130,9 @@
       }
     }
 
-    if (!connection_->WriteDots(sized_cells))
+    if (!connection_->WriteDots(sized_cells)) {
       Disconnect();
+    }
   }
 }
 
@@ -165,8 +167,9 @@
 
 void BrailleControllerImpl::StartConnecting() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (started_connecting_)
+  if (started_connecting_) {
     return;
+  }
   started_connecting_ = true;
   TryLoadLibBrlApi();
   if (!libbrlapi_loader_.loaded() && !skip_libbrlapi_so_load_) {
@@ -269,8 +272,9 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   // Don't reschedule if there's already a connect scheduled or
   // the next attempt would fall outside of the retry limit.
-  if (connect_scheduled_)
+  if (connect_scheduled_) {
     return;
+  }
   if (base::Time::Now() + kConnectionDelay > retry_connect_horizon_) {
     VLOG(1) << "Stopping to retry to connect to brlapi";
     return;
@@ -286,8 +290,9 @@
 
 void BrailleControllerImpl::Disconnect() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (!connection_ || !connection_->Connected())
+  if (!connection_ || !connection_->Connected()) {
     return;
+  }
   connection_->Disconnect();
   DispatchOnDisplayStateChanged(std::make_unique<DisplayState>());
 }
@@ -305,8 +310,9 @@
     int result = connection_->ReadKey(&code);
     if (result < 0) {  // Error.
       brlapi_error_t* err = connection_->BrlapiError();
-      if (err->brlerrno == BRLAPI_ERROR_LIBCERR && err->libcerrno == EINTR)
+      if (err->brlerrno == BRLAPI_ERROR_LIBCERR && err->libcerrno == EINTR) {
         continue;
+      }
       // Disconnect on other errors.
       VLOG(1) << "BrlAPI error: " << connection_->BrlapiStrError();
       Disconnect();
@@ -315,8 +321,9 @@
       return;
     }
     std::unique_ptr<KeyEvent> event = BrlapiKeyCodeToEvent(code);
-    if (event)
+    if (event) {
       DispatchKeyEvent(std::move(event));
+    }
   }
 }
 
@@ -328,8 +335,9 @@
     return;
   }
   VLOG(1) << "Dispatching key event: " << event->ToValue();
-  for (auto& observer : observers_)
+  for (auto& observer : observers_) {
     observer.OnBrailleKeyEvent(*event);
+  }
 }
 
 void BrailleControllerImpl::DispatchOnDisplayStateChanged(
@@ -344,8 +352,9 @@
     }
     return;
   }
-  for (auto& observer : observers_)
+  for (auto& observer : observers_) {
     observer.OnBrailleDisplayStateChanged(*new_state);
+  }
 }
 
 }  // namespace braille_display_private
diff --git a/chrome/browser/extensions/api/braille_display_private/brlapi_connection.cc b/chrome/browser/extensions/api/braille_display_private/brlapi_connection.cc
index a3522ca5..3cff330 100644
--- a/chrome/browser/extensions/api/braille_display_private/brlapi_connection.cc
+++ b/chrome/browser/extensions/api/braille_display_private/brlapi_connection.cc
@@ -82,11 +82,13 @@
   std::array path = {0, 0};
   int pathElements = 0;
 #if BUILDFLAG(IS_CHROMEOS)
-  if (base::SysInfo::IsRunningOnChromeOS())
+  if (base::SysInfo::IsRunningOnChromeOS()) {
     path[pathElements++] = kDefaultTtyChromeOS;
+  }
 #endif
-  if (pathElements == 0 && getenv("WINDOWPATH") == nullptr)
+  if (pathElements == 0 && getenv("WINDOWPATH") == nullptr) {
     path[pathElements++] = kDefaultTtyLinux;
+  }
   if (libbrlapi_loader_->brlapi__enterTtyModeWithPath(
           handle_.get(), &path[0], pathElements, nullptr) < 0) {
     LOG(ERROR) << "brlapi: couldn't enter tty mode: " << BrlapiStrError();
@@ -164,8 +166,9 @@
 
 bool BrlapiConnectionImpl::WriteDots(const std::vector<unsigned char>& cells) {
   // Cells is a 2D vector, compressed into 1D.
-  if (!CheckConnected())
+  if (!CheckConnected()) {
     return false;
+  }
   if (libbrlapi_loader_->brlapi__writeDots(handle_.get(), cells.data()) < 0) {
     VLOG(1) << "Couldn't write to brlapi: " << BrlapiStrError();
     return false;
@@ -174,8 +177,9 @@
 }
 
 int BrlapiConnectionImpl::ReadKey(brlapi_keyCode_t* key_code) {
-  if (!CheckConnected())
+  if (!CheckConnected()) {
     return -1;
+  }
   return libbrlapi_loader_->brlapi__readKey(
       handle_.get(), 0 /*wait*/, key_code);
 }
@@ -190,8 +194,9 @@
       handle_.get(), BRLAPI_PARAM_DEVICE_CELL_SIZE, 0, BRLAPI_PARAMF_GLOBAL,
       &device_cell_size, sizeof(device_cell_size));
 
-  if (result == -1 || result != sizeof(device_cell_size))
+  if (result == -1 || result != sizeof(device_cell_size)) {
     return false;
+  }
 
   *cell_size = device_cell_size;
   return true;
diff --git a/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc b/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc
index dc15f8b..43fc5fe7 100644
--- a/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc
+++ b/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc
@@ -34,12 +34,15 @@
 // Maps the keyboard modifier flags to their corresponding flags in a
 // |KeyEvent|.
 void MapModifierFlags(brlapi_keyCode_t code, KeyEvent* event) {
-  if (code & BRLAPI_KEY_FLG_CONTROL)
+  if (code & BRLAPI_KEY_FLG_CONTROL) {
     event->ctrl_key = true;
-  if (code & BRLAPI_KEY_FLG_META)
+  }
+  if (code & BRLAPI_KEY_FLG_META) {
     event->alt_key = true;
-  if (code & BRLAPI_KEY_FLG_SHIFT)
+  }
+  if (code & BRLAPI_KEY_FLG_SHIFT) {
     event->shift_key = true;
+  }
 }
 
 // Maps a brlapi keysym, which is similar to an X keysym into the
@@ -51,8 +54,9 @@
   if (key_sym < kMaxLatin1KeySym ||
       (key_sym & BRLAPI_KEY_SYM_UNICODE) != 0) {
     base_icu::UChar32 code_point = key_sym & ~BRLAPI_KEY_SYM_UNICODE;
-    if (!base::IsValidCharacter(code_point))
+    if (!base::IsValidCharacter(code_point)) {
       return;
+    }
     event->standard_key_char.emplace();
     base::WriteUnicodeCharacter(code_point, &*event->standard_key_char);
   } else if (key_sym >= kMinFunctionKey && key_sym <= kMaxFunctionKey) {
@@ -147,10 +151,11 @@
           event->braille_dots = dots;
 
           // BRLAPI_DOTC represents when the braille space key is pressed.
-          if (dots && (argument & BRLAPI_DOTC))
+          if (dots && (argument & BRLAPI_DOTC)) {
             event->command = KeyCommand::kChord;
-          else
+          } else {
             event->command = KeyCommand::kDots;
+          }
           MapModifierFlags(code, event);
           break;
       }
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc b/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
index dbab789..73eb914 100644
--- a/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
+++ b/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
@@ -239,8 +239,9 @@
 void BrowsingDataRemoverFunction::OnTaskFinished() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK_GT(pending_tasks_, 0);
-  if (--pending_tasks_ > 0)
+  if (--pending_tasks_ > 0) {
     return;
+  }
   observation_.Reset();
   Respond(NoArguments());
   Release();  // Balanced in StartRemoving.
@@ -369,8 +370,9 @@
     for (const auto& origin : origins_) {
       std::string domain = GetDomainAndRegistry(
           origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
-      if (domain.empty())
+      if (domain.empty()) {
         domain = origin.host();  // IP address or internal hostname.
+      }
       filter_builder->AddRegisterableDomain(domain);
     }
     remover->RemoveWithFilterAndReply(
@@ -400,11 +402,13 @@
 
   const base::Value* origin_type_dict =
       options.Find(extension_browsing_data_api_constants::kOriginTypesKey);
-  if (!origin_type_dict)
+  if (!origin_type_dict) {
     return true;
+  }
 
-  if (!origin_type_dict->is_dict())
+  if (!origin_type_dict->is_dict()) {
     return false;
+  }
 
   const base::DictValue& origin_type = origin_type_dict->GetDict();
 
@@ -415,8 +419,9 @@
   const base::Value* option = origin_type.Find(
       extension_browsing_data_api_constants::kUnprotectedWebKey);
   if (option) {
-    if (!option->is_bool())
+    if (!option->is_bool()) {
       return false;
+    }
 
     *origin_type_mask |=
         option->GetBool()
@@ -428,8 +433,9 @@
   option =
       origin_type.Find(extension_browsing_data_api_constants::kProtectedWebKey);
   if (option) {
-    if (!option->is_bool())
+    if (!option->is_bool()) {
       return false;
+    }
 
     *origin_type_mask |=
         option->GetBool()
@@ -441,8 +447,9 @@
   option =
       origin_type.Find(extension_browsing_data_api_constants::kExtensionsKey);
   if (option) {
-    if (!option->is_bool())
+    if (!option->is_bool()) {
       return false;
+    }
 
     *origin_type_mask |=
         option->GetBool() ? chrome_browsing_data_remover::ORIGIN_TYPE_EXTENSION
@@ -475,14 +482,16 @@
 // Returns false if parse was not successful, i.e. if 'dataToRemove' is not
 // present or any data-type keys don't have supported (boolean) values.
 bool BrowsingDataRemoveFunction::GetRemovalMask(uint64_t* removal_mask) {
-  if (args().size() <= 1 || !args()[1].is_dict())
+  if (args().size() <= 1 || !args()[1].is_dict()) {
     return false;
+  }
 
   std::vector<std::string> unsupported_data_types;
   *removal_mask = 0;
   for (const auto kv : args()[1].GetDict()) {
-    if (!kv.second.is_bool())
+    if (!kv.second.is_bool()) {
       return false;
+    }
     if (kv.second.GetBool()) {
       uint64_t mask = MaskForKey(kv.first.c_str());
       if (mask == 0) {
diff --git a/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc b/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
index 4aff4e36..ee06ccf 100644
--- a/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
+++ b/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
@@ -103,14 +103,17 @@
 
   void GetBucketsForArgs(const base::ListValue& args,
                          QuotaLimitHeuristic::BucketList* buckets) override {
-    if (args.empty())
+    if (args.empty()) {
       return;
+    }
     const base::DictValue* details = args.front().GetIfDict();
-    if (!details)
+    if (!details) {
       return;
+    }
     std::optional<int> sign_request_id = details->FindInt("signRequestId");
-    if (!sign_request_id.has_value())
+    if (!sign_request_id.has_value()) {
       return;
+    }
     if (*sign_request_id > biggest_request_id_) {
       // Either it's the first request with the newly issued requestId, or it's
       // an invalid requestId (bigger than the real one). Return a new bucket in
@@ -178,8 +181,9 @@
     std::string* out_error_message) {
   out_info->certificate =
       ParseCertificateDer(info.certificate, out_error_message);
-  if (!out_info->certificate)
+  if (!out_info->certificate) {
     return false;
+  }
 
   out_info->supported_algorithms.reserve(info.supported_hashes.size());
   for (const api_cp::Hash hash : info.supported_hashes) {
@@ -226,8 +230,9 @@
   }
   out_info->certificate =
       ParseCertificateDer(info.certificate_chain[0], out_error_message);
-  if (!out_info->certificate)
+  if (!out_info->certificate) {
     return false;
+  }
 
   out_info->supported_algorithms.reserve(info.supported_algorithms.size());
   for (const api_cp::Algorithm algorithm : info.supported_algorithms) {
@@ -454,8 +459,9 @@
 
   int attempts_left = -1;
   if (params->details.attempts_left) {
-    if (*params->details.attempts_left < 0)
+    if (*params->details.attempts_left < 0) {
       return RespondNow(Error(kCertificateProviderInvalidAttemptsLeft));
+    }
     attempts_left = *params->details.attempts_left;
   }
 
@@ -580,8 +586,9 @@
 
   std::vector<uint8_t> signature;
   // If an error occurred, |signature| will not be set.
-  if (params->signature)
+  if (params->signature) {
     signature.assign(params->signature->begin(), params->signature->end());
+  }
 
   if (!service->ReplyToSignRequest(extension_id(), params->request_id,
                                    signature)) {
diff --git a/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc b/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
index 06c20d6..134b4b6 100644
--- a/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
+++ b/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
@@ -133,8 +133,9 @@
   // RSA-PSS is not supported for prehashed data.
   EXPECT_FALSE(SSL_is_signature_algorithm_rsa_pss(openssl_signature_algorithm));
   RSA* rsa_key = EVP_PKEY_get0_RSA(key.key());
-  if (!rsa_key)
+  if (!rsa_key) {
     return false;
+  }
   const int digest_algorithm_nid = EVP_MD_type(
       SSL_get_signature_algorithm_digest(openssl_signature_algorithm));
   unsigned len = 0;
@@ -298,8 +299,9 @@
 
   std::unique_ptr<net::test_server::HttpResponse> OnHttpsServerRequested(
       const net::test_server::HttpRequest& request) const {
-    if (request.relative_url != kClientCertUrl)
+    if (request.relative_url != kClientCertUrl) {
       return nullptr;
+    }
     auto response = std::make_unique<net::test_server::BasicHttpResponse>();
     if (!request.ssl_info || !request.ssl_info->cert) {
       response->set_code(net::HTTP_FORBIDDEN);
@@ -563,8 +565,9 @@
   }
 
   bool SendCommand(const std::string& command) {
-    if (!command_request_listener_->WaitUntilSatisfied())
+    if (!command_request_listener_->WaitUntilSatisfied()) {
       return false;
+    }
     command_request_listener_->Reply(command);
     command_request_listener_->Reset();
     return true;
@@ -573,8 +576,9 @@
   bool SendCommandAndWaitForMessage(const std::string& command,
                                     const std::string& expected_message) {
     ExtensionTestMessageListener listener(expected_message);
-    if (!SendCommand(command))
+    if (!SendCommand(command)) {
       return false;
+    }
     return listener.WaitUntilSatisfied();
   }
 
@@ -986,8 +990,9 @@
                        ShowPinDialogWrongPinThreeTimes) {
   AddFakeSignRequest(kFakeSignRequestId);
   NavigateTo("basic.html");
-  for (int i = 0; i < kWrongPinAttemptsLimit; i++)
+  for (int i = 0; i < kWrongPinAttemptsLimit; i++) {
     EnterWrongPinAndWaitForMessage();
+  }
 
   // The textfield has to be disabled, as extension does not allow input now.
   EXPECT_FALSE(GetActivePinDialogView()->textfield_for_testing()->GetEnabled());
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_api.cc b/chrome/browser/extensions/api/content_settings/content_settings_api.cc
index ffa462b..ca2d3e66 100644
--- a/chrome/browser/extensions/api/content_settings/content_settings_api.cc
+++ b/chrome/browser/extensions/api/content_settings/content_settings_api.cc
@@ -50,8 +50,9 @@
 
 bool RemoveContentType(base::ListValue& args,
                        ContentSettingsType* content_type) {
-  if (args.empty() || !args[0].is_string())
+  if (args.empty() || !args[0].is_string()) {
     return false;
+  }
 
   // Not a ref since we remove the underlying value after.
   std::string content_type_str = args[0].GetString();
@@ -143,10 +144,12 @@
   }
 
   bool incognito = false;
-  if (params->details.incognito)
+  if (params->details.incognito) {
     incognito = *params->details.incognito;
-  if (incognito && !include_incognito_information())
+  }
+  if (incognito && !include_incognito_information()) {
     return RespondNow(Error(extension_misc::kIncognitoErrorMessage));
+  }
 
   HostContentSettingsMap* map;
   scoped_refptr<content_settings::CookieSettings> cookie_settings;
@@ -205,16 +208,18 @@
   ContentSettingsPattern primary_pattern =
       content_settings_helpers::ParseExtensionPattern(
           params->details.primary_pattern, &primary_error);
-  if (!primary_pattern.IsValid())
+  if (!primary_pattern.IsValid()) {
     return RespondNow(Error(primary_error));
+  }
 
   ContentSettingsPattern secondary_pattern = ContentSettingsPattern::Wildcard();
   if (params->details.secondary_pattern) {
     std::string secondary_error;
     secondary_pattern = content_settings_helpers::ParseExtensionPattern(
         *params->details.secondary_pattern, &secondary_error);
-    if (!secondary_pattern.IsValid())
+    if (!secondary_pattern.IsValid()) {
       return RespondNow(Error(secondary_error));
+    }
   }
 
   EXTENSION_FUNCTION_VALIDATE(params->details.setting.is_string());
@@ -306,8 +311,9 @@
   } else {
     // Incognito profiles can't access regular mode ever, they only exist in
     // split mode.
-    if (browser_context()->IsOffTheRecord())
+    if (browser_context()->IsOffTheRecord()) {
       return RespondNow(Error(kIncognitoContextError));
+    }
   }
 
   if (scope == ChromeSettingScope::kIncognitoSessionOnly &&
diff --git a/chrome/browser/extensions/api/context_menus/context_menus_api.cc b/chrome/browser/extensions/api/context_menus/context_menus_api.cc
index 9d9e5f3..ca3d6287 100644
--- a/chrome/browser/extensions/api/context_menus/context_menus_api.cc
+++ b/chrome/browser/extensions/api/context_menus/context_menus_api.cc
@@ -42,8 +42,9 @@
   if (params->create_properties.id) {
     id.string_uid = *params->create_properties.id;
   } else {
-    if (BackgroundInfo::HasLazyContext(extension()))
+    if (BackgroundInfo::HasLazyContext(extension())) {
       return RespondNow(Error(kIdRequiredError));
+    }
 
     // The Generated Id is added by context_menus_custom_bindings.js.
     EXTENSION_FUNCTION_VALIDATE(args().size() >= 1);
@@ -113,8 +114,9 @@
                             context_menu_helpers::GetIDString(id)));
   }
 
-  if (!manager->RemoveContextMenuItem(id))
+  if (!manager->RemoveContextMenuItem(id)) {
     return RespondNow(Error("Cannot remove menu item."));
+  }
   manager->WriteToStorage(extension(), id.extension_key);
   return RespondNow(NoArguments());
 }
diff --git a/chrome/browser/extensions/api/context_menus/extension_context_menu_browsertest.cc b/chrome/browser/extensions/api/context_menus/extension_context_menu_browsertest.cc
index 2f796408..ef6d5b21 100644
--- a/chrome/browser/extensions/api/context_menus/extension_context_menu_browsertest.cc
+++ b/chrome/browser/extensions/api/context_menus/extension_context_menu_browsertest.cc
@@ -139,8 +139,9 @@
     const ExtensionSet& extensions =
         ExtensionRegistry::Get(profile())->enabled_extensions();
     for (const auto& ext : extensions) {
-      if (ext->name() == name)
+      if (ext->name() == name) {
         return ext.get();
+      }
     }
     return nullptr;
   }
@@ -153,8 +154,9 @@
         menu_manager()->ExtensionIds();
     for (const auto& extension_id : extension_ids) {
       const MenuItem::OwnedList* list = menu_manager()->MenuItems(extension_id);
-      for (const auto& item : *list)
+      for (const auto& item : *list) {
         result.push_back(item.get());
+      }
     }
     return result;
   }
@@ -177,10 +179,11 @@
   std::string ClickMenuInFrame(content::RenderFrameHost* frame,
                                const std::string& target_menu_item_id) {
     content::ContextMenuParams params;
-    if (frame->GetParent())
+    if (frame->GetParent()) {
       params.frame_url = frame->GetLastCommittedURL();
-    else
+    } else {
       params.page_url = frame->GetLastCommittedURL();
+    }
 
     std::unique_ptr<PlatformContextMenu> menu =
         CreateContextMenu(frame, params);
@@ -194,8 +197,9 @@
 
     ExtensionTestMessageListener listener;
     menu->ExecuteCommand(command_id, 0);
-    if (!listener.WaitUntilSatisfied())
+    if (!listener.WaitUntilSatisfied()) {
       return "Onclick never fired for menu item: " + target_menu_item_id;
+    }
 
     return listener.message();
   }
@@ -207,8 +211,9 @@
       const MenuItem::Id& id = it.second;
       std::u16string tmp_label;
       EXPECT_TRUE(GetItemLabel(menu, id, &tmp_label));
-      if (tmp_label == label16)
+      if (tmp_label == label16) {
         return true;
+      }
     }
     return false;
   }
@@ -220,8 +225,9 @@
                     const MenuItem::Id& id,
                     std::u16string* result) const {
     int command_id = 0;
-    if (!FindCommandId(menu, id, &command_id))
+    if (!FindCommandId(menu, id, &command_id)) {
       return false;
+    }
 
     std::optional<std::pair<MenuModel*, size_t>> model_and_index =
         menu->GetMenuModelAndItemIndex(command_id);
@@ -325,10 +331,11 @@
 
     ASSERT_TRUE(begin.WaitUntilSatisfied());
 
-    if (enabled)
+    if (enabled) {
       begin.Reply("start enabled");
-    else
+    } else {
       begin.Reply("start disabled");
+    }
 
     // Wait for the extension to tell us it's created an item.
     ASSERT_TRUE(create.WaitUntilSatisfied());
@@ -918,8 +925,9 @@
 // Not relevant on Android, which only supports service worker.
 IN_PROC_BROWSER_TEST_P(ExtensionContextMenuLazyTest, EventPage) {
   // This test is event page-specific.
-  if (GetParam() == ContextType::kServiceWorker)
+  if (GetParam() == ContextType::kServiceWorker) {
     return;
+  }
   GURL about_blank("about:blank");
   ExtensionHostTestHelper host_helper(profile());
   host_helper.RestrictToType(mojom::ViewType::kExtensionBackgroundPage);
@@ -967,8 +975,9 @@
 IN_PROC_BROWSER_TEST_P(ExtensionContextMenuLazyTest,
                        MAYBE_IncognitoSplitContextMenuCount) {
   // TODO(crbug.com/40617251): Not yet implemented.
-  if (GetParam() == ContextType::kServiceWorker)
+  if (GetParam() == ContextType::kServiceWorker) {
     return;
+  }
   ExtensionTestMessageListener created("created item regular");
   ExtensionTestMessageListener created_incognito("created item incognito");
 
diff --git a/chrome/browser/extensions/api/cookies/cookies_api.cc b/chrome/browser/extensions/api/cookies/cookies_api.cc
index a050006d..8121a20f 100644
--- a/chrome/browser/extensions/api/cookies/cookies_api.cc
+++ b/chrome/browser/extensions/api/cookies/cookies_api.cc
@@ -276,8 +276,9 @@
   network::mojom::CookieManager* cookie_manager =
       profile->GetDefaultStoragePartition()
           ->GetCookieManagerForBrowserProcess();
-  if (!cookie_manager)
+  if (!cookie_manager) {
     return;
+  }
 
   cookie_manager->AddGlobalChangeListener(receiver->BindNewPipeAndPassRemote());
   receiver->set_disconnect_handler(
@@ -299,8 +300,9 @@
                                        base::ListValue event_args,
                                        const GURL& cookie_domain) {
   EventRouter* router = context ? EventRouter::Get(context) : nullptr;
-  if (!router)
+  if (!router) {
     return;
+  }
   auto event = std::make_unique<Event>(histogram_value, event_name,
                                        std::move(event_args), context);
   event->event_url = cookie_domain;
@@ -316,14 +318,16 @@
 
   // Read/validate input parameters.
   std::string error;
-  if (!ParseUrl(extension(), parsed_args_->details.url, &url_, true, &error))
+  if (!ParseUrl(extension(), parsed_args_->details.url, &url_, true, &error)) {
     return RespondNow(Error(std::move(error)));
+  }
 
   std::string store_id = parsed_args_->details.store_id.value_or(std::string());
   network::mojom::CookieManager* cookie_manager = ParseStoreCookieManager(
       browser_context(), include_incognito_information(), &store_id, &error);
-  if (!cookie_manager)
+  if (!cookie_manager) {
     return RespondNow(Error(std::move(error)));
+  }
 
   if (parsed_args_->details.partition_key.has_value() &&
       !parsed_args_->details.partition_key->has_cross_site_ancestor
@@ -346,8 +350,9 @@
     return RespondNow(Error(std::move(partition_key.error())));
   }
 
-  if (!parsed_args_->details.store_id)
+  if (!parsed_args_->details.store_id) {
     parsed_args_->details.store_id = store_id;
+  }
 
   DCHECK(!url_.is_empty() && url_.is_valid());
   cookies_helpers::GetCookieListFromManager(
@@ -427,8 +432,9 @@
   std::string store_id = parsed_args_->details.store_id.value_or(std::string());
   network::mojom::CookieManager* cookie_manager = ParseStoreCookieManager(
       browser_context(), include_incognito_information(), &store_id, &error);
-  if (!cookie_manager)
+  if (!cookie_manager) {
     return RespondNow(Error(std::move(error)));
+  }
 
   // make sure user input is valid
   base::expected<std::optional<net::CookiePartitionKey>, std::string>
@@ -438,8 +444,9 @@
     return RespondNow(Error(std::move(partition_key.error())));
   }
 
-  if (!parsed_args_->details.store_id)
+  if (!parsed_args_->details.store_id) {
     parsed_args_->details.store_id = store_id;
+  }
 
   net::CookiePartitionKeyCollection cookie_partition_key_collection =
       cookies_helpers::CookiePartitionKeyCollectionFromApiPartitionKey(
@@ -532,14 +539,16 @@
 
   // Read/validate input parameters.
   std::string error;
-  if (!ParseUrl(extension(), parsed_args_->details.url, &url_, true, &error))
+  if (!ParseUrl(extension(), parsed_args_->details.url, &url_, true, &error)) {
     return RespondNow(Error(std::move(error)));
+  }
 
   std::string store_id = parsed_args_->details.store_id.value_or(std::string());
   network::mojom::CookieManager* cookie_manager = ParseStoreCookieManager(
       browser_context(), include_incognito_information(), &store_id, &error);
-  if (!cookie_manager)
+  if (!cookie_manager) {
     return RespondNow(Error(std::move(error)));
+  }
 
   // cookies.set api allows for an partitionKey with a `top_level_site` present
   // but no value for `has_cross_site_ancestor`. If that is the case, the
@@ -571,8 +580,9 @@
     return RespondNow(Error(std::move(net_partition_key.error())));
   }
 
-  if (!parsed_args_->details.store_id)
+  if (!parsed_args_->details.store_id) {
     parsed_args_->details.store_id = store_id;
+  }
 
   base::Time expiration_time;
   if (parsed_args_->details.expiration_date) {
@@ -709,14 +719,16 @@
 
   // Read/validate input parameters.
   std::string error;
-  if (!ParseUrl(extension(), parsed_args_->details.url, &url_, true, &error))
+  if (!ParseUrl(extension(), parsed_args_->details.url, &url_, true, &error)) {
     return RespondNow(Error(std::move(error)));
+  }
 
   std::string store_id = parsed_args_->details.store_id.value_or(std::string());
   network::mojom::CookieManager* cookie_manager = ParseStoreCookieManager(
       browser_context(), include_incognito_information(), &store_id, &error);
-  if (!cookie_manager)
+  if (!cookie_manager) {
     return RespondNow(Error(std::move(error)));
+  }
 
   base::expected<std::optional<net::CookiePartitionKey>, std::string>
       partition_key = cookies_helpers::ToNetCookiePartitionKey(
@@ -725,8 +737,9 @@
     return RespondNow(Error(std::move(partition_key.error())));
   }
 
-  if (!parsed_args_->details.store_id)
+  if (!parsed_args_->details.store_id) {
     parsed_args_->details.store_id = store_id;
+  }
 
   network::mojom::CookieDeletionFilterPtr filter(
       network::mojom::CookieDeletionFilter::New());
diff --git a/chrome/browser/extensions/api/cookies/cookies_helpers.cc b/chrome/browser/extensions/api/cookies/cookies_helpers.cc
index 7038ece..3fa1b11 100644
--- a/chrome/browser/extensions/api/cookies/cookies_helpers.cc
+++ b/chrome/browser/extensions/api/cookies/cookies_helpers.cc
@@ -49,8 +49,9 @@
   // Ignore any cookie whose domain doesn't match the extension's
   // host permissions.
   GURL cookie_domain_url = cookies_helpers::GetURLFromCanonicalCookie(cookie);
-  if (!extension->permissions_data()->HasHostPermission(cookie_domain_url))
+  if (!extension->permissions_data()->HasHostPermission(cookie_domain_url)) {
     return;
+  }
   // Filter the cookie using the match filter.
   cookies_helpers::MatchFilter filter(details);
   // There is an edge case where a getAll call that contains a
@@ -78,10 +79,12 @@
   bool allow_original = !profile->IsOffTheRecord();
   bool allow_incognito = profile->IsOffTheRecord() ||
                          (include_incognito && profile->HasPrimaryOTRProfile());
-  if (store_id == kOriginalProfileStoreId && allow_original)
+  if (store_id == kOriginalProfileStoreId && allow_original) {
     return profile->GetOriginalProfile();
-  if (store_id == kOffTheRecordProfileStoreId && allow_incognito)
+  }
+  if (store_id == kOffTheRecordProfileStoreId && allow_incognito) {
     return profile->GetPrimaryOTRProfile(/*create_if_needed=*/true);
+  }
   return nullptr;
 }
 
@@ -455,21 +458,25 @@
     return true;
   }
 
-  if (details_->name && *details_->name != cookie.Name())
+  if (details_->name && *details_->name != cookie.Name()) {
     return false;
+  }
 
-  if (!MatchesDomain(cookie.Domain()))
+  if (!MatchesDomain(cookie.Domain())) {
     return false;
+  }
 
-  if (details_->path && *details_->path != cookie.Path())
+  if (details_->path && *details_->path != cookie.Path()) {
     return false;
+  }
 
   if (details_->secure && *details_->secure != cookie.SecureAttribute()) {
     return false;
   }
 
-  if (details_->session && *details_->session != !cookie.IsPersistent())
+  if (details_->session && *details_->session != !cookie.IsPersistent()) {
     return false;
+  }
 
   return true;
 }
@@ -480,23 +487,27 @@
 }
 
 bool MatchFilter::MatchesDomain(const std::string& domain) {
-  if (!details_->domain)
+  if (!details_->domain) {
     return true;
+  }
 
   // Add a leading '.' character to the filter domain if it doesn't exist.
-  if (net::cookie_util::DomainIsHostOnly(*details_->domain))
+  if (net::cookie_util::DomainIsHostOnly(*details_->domain)) {
     details_->domain->insert(0, ".");
+  }
 
   std::string sub_domain(domain);
   // Strip any leading '.' character from the input cookie domain.
-  if (!net::cookie_util::DomainIsHostOnly(sub_domain))
+  if (!net::cookie_util::DomainIsHostOnly(sub_domain)) {
     sub_domain = sub_domain.substr(1);
+  }
 
   // Now check whether the domain argument is a subdomain of the filter domain.
   for (sub_domain.insert(0, ".");
        sub_domain.length() >= details_->domain->length();) {
-    if (sub_domain == *details_->domain)
+    if (sub_domain == *details_->domain) {
       return true;
+    }
     const size_t next_dot = sub_domain.find('.', 1);  // Skip over leading dot.
     sub_domain.erase(0, next_dot);
   }
diff --git a/chrome/browser/extensions/api/cookies/cookies_unittest.cc b/chrome/browser/extensions/api/cookies/cookies_unittest.cc
index 43ac39b..42903b7b 100644
--- a/chrome/browser/extensions/api/cookies/cookies_unittest.cc
+++ b/chrome/browser/extensions/api/cookies/cookies_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/values.h"
 #include "chrome/browser/extensions/api/cookies/cookies_helpers.h"
 #include "chrome/common/extensions/api/cookies.h"
+#include "chrome/test/base/chrome_test_utils.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/browser_task_environment.h"
 #include "extensions/buildflags/buildflags.h"
@@ -47,7 +48,9 @@
 
 }  // namespace
 
-class ExtensionCookiesTest : public testing::Test {
+class ExtensionCookiesTest
+    : public chrome_test_utils::TestingBrowserProcessDeathTestMixin,
+      public testing::Test {
  private:
   content::BrowserTaskEnvironment task_environment_;
 };
diff --git a/chrome/browser/extensions/api/debugger/debugger_api.cc b/chrome/browser/extensions/api/debugger/debugger_api.cc
index f9e38b0..3fb6d4a 100644
--- a/chrome/browser/extensions/api/debugger/debugger_api.cc
+++ b/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -148,10 +148,12 @@
                                        DevToolsAgentHost& agent_host) {
   Profile* profile =
       Profile::FromBrowserContext(agent_host.GetBrowserContext());
-  if (!profile)
+  if (!profile) {
     return false;
-  if (!extension_profile->IsSameOrParent(profile))
+  }
+  if (!extension_profile->IsSameOrParent(profile)) {
     return false;
+  }
   return profile == extension_profile || allow_incognito_access;
 }
 
@@ -162,11 +164,13 @@
                              const GURL& url,
                              std::string* error) {
   // Allow the extension to attach to about:blank and empty URLs.
-  if (url.is_empty() || url == "about:")
+  if (url.is_empty() || url == "about:") {
     return true;
+  }
 
-  if (url == content::kUnreachableWebDataURL)
+  if (url == content::kUnreachableWebDataURL) {
     return true;
+  }
 
   // NOTE: The `debugger` permission implies all URLs access (and indicates
   // such to the user), so we don't check explicit page access. However, we
@@ -568,14 +572,16 @@
 }
 
 void ExtensionDevToolsClientHost::RespondDetachedToPendingRequests() {
-  for (const auto& it : pending_requests_)
+  for (const auto& it : pending_requests_) {
     it.second->SendDetachedError();
+  }
   pending_requests_.clear();
 }
 
 void ExtensionDevToolsClientHost::SendDetachedEvent() {
-  if (!EventRouter::Get(profile_))
+  if (!EventRouter::Get(profile_)) {
     return;
+  }
 
   auto args(OnDetach::Create(debuggee_, detach_reason_));
   auto event =
@@ -595,8 +601,9 @@
     content::BrowserContext* browser_context,
     const Extension* extension,
     UnloadedExtensionReason reason) {
-  if (extension->id() == extension_id())
+  if (extension->id() == extension_id()) {
     Close();
+  }
 }
 
 void ExtensionDevToolsClientHost::OnAppTerminating() {
@@ -607,8 +614,9 @@
     DevToolsAgentHost* agent_host,
     base::span<const uint8_t> message) {
   DCHECK(agent_host == agent_host_.get());
-  if (!EventRouter::Get(profile_))
+  if (!EventRouter::Get(profile_)) {
     return;
+  }
 
   std::string_view message_str = base::as_string_view(message);
   std::optional<base::Value> result = base::JSONReader::Read(
@@ -622,8 +630,9 @@
   std::optional<int> id = dictionary.FindInt("id");
   if (!id) {
     std::string* method_name = dictionary.FindString("method");
-    if (!method_name)
+    if (!method_name) {
       return;
+    }
 
     OnEvent::Params params;
     if (base::DictValue* params_value = dictionary.FindDict("params")) {
@@ -642,8 +651,9 @@
                                                          std::move(event));
   } else {
     auto it = pending_requests_.find(*id);
-    if (it == pending_requests_.end())
+    if (it == pending_requests_.end()) {
       return;
+    }
 
     it->second->SendResponseBody(base::Value(std::move(dictionary)));
     pending_requests_.erase(it);
@@ -659,8 +669,9 @@
 
 bool ExtensionDevToolsClientHost::MayAttachToURL(const GURL& url,
                                                  bool is_webui) {
-  if (is_webui)
+  if (is_webui) {
     return false;
+  }
   std::string error;
   return ExtensionMayAttachToURLOrInnerURL(*extension_, profile_, url, nullptr,
                                            &error);
@@ -778,8 +789,9 @@
 }
 
 bool DebuggerFunction::InitClientHost(std::string* error) {
-  if (!InitAgentHost(error))
+  if (!InitAgentHost(error)) {
     return false;
+  }
 
   client_host_ = FindClientHost();
   if (!client_host_) {
@@ -791,8 +803,9 @@
 }
 
 ExtensionDevToolsClientHost* DebuggerFunction::FindClientHost() {
-  if (!agent_host_.get())
+  if (!agent_host_.get()) {
     return nullptr;
+  }
 
   const ExtensionId& extension_id = extension()->id();
   DevToolsAgentHost* agent_host = agent_host_.get();
@@ -819,8 +832,9 @@
 
   CopyDebuggee(&debuggee_, params->target);
   std::string error;
-  if (!InitAgentHost(&error))
+  if (!InitAgentHost(&error)) {
     return RespondNow(Error(std::move(error)));
+  }
 
   if (!DevToolsAgentHost::IsSupportedProtocolVersion(
           params->required_version)) {
@@ -865,8 +879,9 @@
 
   CopyDebuggee(&debuggee_, params->target);
   std::string error;
-  if (!InitClientHost(&error))
+  if (!InitClientHost(&error)) {
     return RespondNow(Error(std::move(error)));
+  }
 
   client_host_->RespondDetachedToPendingRequests();
   client_host_->Close();
@@ -886,14 +901,16 @@
 
   DebuggeeFromDebuggerSession(debuggee_, params->target);
   std::string error;
-  if (!InitClientHost(&error))
+  if (!InitClientHost(&error)) {
     return RespondNow(Error(std::move(error)));
+  }
 
   client_host_->SendMessageToBackend(
       this, params->method, base::OptionalToPtr(params->command_params),
       params->target.session_id);
-  if (did_respond())
+  if (did_respond()) {
     return AlreadyResponded();
+  }
   return RespondLater();
 }
 
@@ -966,8 +983,9 @@
   dictionary.Set(kTargetTypeField, target_type);
 
   GURL favicon_url = host->GetFaviconURL();
-  if (favicon_url.is_valid())
+  if (favicon_url.is_valid()) {
     dictionary.Set(kTargetFaviconUrlField, favicon_url.spec());
+  }
 
   return dictionary;
 }
@@ -986,8 +1004,9 @@
     // TODO(crbug.com/40233332): hide all Tab targets for now to avoid
     // compatibility problems. Consider exposing them later when they're fully
     // supported, and compatibility considerations are better understood.
-    if (host->GetType() == DevToolsAgentHost::kTypeTab)
+    if (host->GetType() == DevToolsAgentHost::kTypeTab) {
       continue;
+    }
     if (!ExtensionMayAttachToTargetProfile(
             profile, include_incognito_information(), *host)) {
       continue;
diff --git a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
index 6af9af58..2b0263b 100644
--- a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
+++ b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
@@ -66,8 +66,9 @@
 ChromeContentRulesRegistry::EvaluationScope::~EvaluationScope() {
   registry_->evaluation_disposition_ = previous_disposition_;
   if (registry_->evaluation_disposition_ == EVALUATE_REQUESTS) {
-    for (content::WebContents* tab : registry_->evaluation_pending_)
+    for (content::WebContents* tab : registry_->evaluation_pending_) {
       registry_->EvaluateConditionsForTab(tab);
+    }
     registry_->evaluation_pending_.clear();
   }
 }
@@ -170,8 +171,9 @@
   for (const base::Value& value : api_rule.conditions) {
     conditions.push_back(
         CreateContentCondition(extension, predicate_factories, value, error));
-    if (!error->empty())
+    if (!error->empty()) {
       return nullptr;
+    }
   }
 
   std::vector<std::unique_ptr<const ContentAction>> actions;
@@ -184,8 +186,9 @@
 
     actions.push_back(ContentAction::Create(browser_context(), extension,
                                             value.GetDict(), error));
-    if (!error->empty())
+    if (!error->empty()) {
       return nullptr;
+    }
   }
 
   // Note: |api_rule| may contain tags, but these are ignored.
@@ -229,8 +232,9 @@
 
     for (const std::unique_ptr<const ContentCondition>& condition :
          rule->conditions) {
-      if (EvaluateConditionForTab(condition.get(), tab))
+      if (EvaluateConditionForTab(condition.get(), tab)) {
         matching_rules.insert(rule);
+      }
     }
   }
   return matching_rules;
@@ -326,8 +330,9 @@
     // Skip unknown rules.
     auto content_rules_entry =
         content_rules_.find(std::make_pair(extension_id, id));
-    if (content_rules_entry == content_rules_.end())
+    if (content_rules_entry == content_rules_.end()) {
       continue;
+    }
 
     const ContentRule* rule = content_rules_entry->second.get();
 
@@ -337,8 +342,9 @@
         ContentAction::ApplyInfo apply_info =
             {rule->extension, browser_context(), tab_rules_pair.first,
              rule->priority};
-        for (const auto& action : rule->actions)
+        for (const auto& action : rule->actions) {
           action->Revert(apply_info);
+        }
         tab_rules_pair.second.erase(rule);
       }
     }
@@ -353,8 +359,9 @@
     evaluator->StopTrackingPredicates(predicate_groups_to_stop_tracking);
 
   // Remove the rules.
-  for (auto it : rules_to_erase)
+  for (auto it : rules_to_erase) {
     content_rules_.erase(it);
+  }
 
   return std::string();
 }
@@ -365,8 +372,9 @@
   std::vector<std::string> rule_identifiers;
   for (const RulesMap::value_type& id_rule_pair : content_rules_) {
     const ExtensionIdRuleIdPair& extension_id_rule_id_pair = id_rule_pair.first;
-    if (extension_id_rule_id_pair.first == extension_id)
+    if (extension_id_rule_id_pair.first == extension_id) {
       rule_identifiers.push_back(extension_id_rule_id_pair.second);
+    }
   }
 
   return RemoveRulesImpl(extension_id, rule_identifiers);
@@ -386,33 +394,38 @@
     ContentAction::ApplyInfo apply_info =
         {rule->extension, browser_context(), tab, rule->priority};
     if (!prev_matching_rules.contains(rule)) {
-      for (const std::unique_ptr<const ContentAction>& action : rule->actions)
+      for (const std::unique_ptr<const ContentAction>& action : rule->actions) {
         action->Apply(apply_info);
+      }
     } else {
-      for (const std::unique_ptr<const ContentAction>& action : rule->actions)
+      for (const std::unique_ptr<const ContentAction>& action : rule->actions) {
         action->Reapply(apply_info);
+      }
     }
   }
   for (const ContentRule* rule : prev_matching_rules) {
     if (!matching_rules.contains(rule)) {
       ContentAction::ApplyInfo apply_info =
           {rule->extension, browser_context(), tab, rule->priority};
-      for (const std::unique_ptr<const ContentAction>& action : rule->actions)
+      for (const std::unique_ptr<const ContentAction>& action : rule->actions) {
         action->Revert(apply_info);
+      }
     }
   }
 
-  if (matching_rules.empty())
+  if (matching_rules.empty()) {
     active_rules_[tab].clear();
-  else
+  } else {
     swap(matching_rules, prev_matching_rules);
+  }
 }
 
 bool
 ChromeContentRulesRegistry::ShouldEvaluateExtensionRulesForIncognitoRenderer(
     const Extension* extension) const {
-  if (!util::IsIncognitoEnabled(extension->id(), browser_context()))
+  if (!util::IsIncognitoEnabled(extension->id(), browser_context())) {
     return false;
+  }
 
   // Split-mode incognito extensions register their rules with separate
   // RulesRegistries per Original/OffTheRecord browser contexts, whereas
@@ -427,8 +440,9 @@
     // OffTheRecord registries may have (separate) rules for this extension.
     // Since we're looking at an incognito renderer, so only the OffTheRecord
     // registry should process its rules.
-    if (!browser_context()->IsOffTheRecord())
+    if (!browser_context()->IsOffTheRecord()) {
       return false;
+    }
   }
 
   return true;
@@ -436,8 +450,9 @@
 
 size_t ChromeContentRulesRegistry::GetActiveRulesCountForTesting() {
   size_t count = 0;
-  for (const auto& web_contents_rules_pair : active_rules_)
+  for (const auto& web_contents_rules_pair : active_rules_) {
     count += web_contents_rules_pair.second.size();
+  }
   return count;
 }
 
diff --git a/chrome/browser/extensions/api/declarative_content/content_action.cc b/chrome/browser/extensions/api/declarative_content/content_action.cc
index 2f283321..b1c32f5 100644
--- a/chrome/browser/extensions/api/declarative_content/content_action.cc
+++ b/chrome/browser/extensions/api/declarative_content/content_action.cc
@@ -249,8 +249,9 @@
     const base::DictValue* dict,
     std::string* error) {
   ScriptData script_data;
-  if (!InitScriptData(dict, error, &script_data))
+  if (!InitScriptData(dict, error, &script_data)) {
     return nullptr;
+  }
 
   RecordContentActionCreated(
       declarative_content_constants::ContentActionType::kRequestContentScript);
@@ -283,15 +284,17 @@
   }
   if (const base::Value* all_frames_val =
           dict->Find(declarative_content_constants::kAllFrames)) {
-    if (!all_frames_val->is_bool())
+    if (!all_frames_val->is_bool()) {
       return false;
+    }
 
     script_data->all_frames = all_frames_val->GetBool();
   }
   if (const base::Value* match_about_blank_val =
           dict->Find(declarative_content_constants::kMatchAboutBlank)) {
-    if (!match_about_blank_val->is_bool())
+    if (!match_about_blank_val->is_bool()) {
       return false;
+    }
 
     script_data->match_about_blank = match_about_blank_val->GetBool();
   }
@@ -456,9 +459,10 @@
 
   ContentActionFactory& factory = GetContentActionFactory();
   auto factory_method_iter = factory.factory_methods.find(*instance_type);
-  if (factory_method_iter != factory.factory_methods.end())
+  if (factory_method_iter != factory.factory_methods.end()) {
     return (*factory_method_iter->second)(browser_context, extension,
                                           &json_action_dict, error);
+  }
 
   *error =
       base::StringPrintf(kInvalidInstanceTypeError, instance_type->c_str());
diff --git a/chrome/browser/extensions/api/declarative_content/content_condition.cc b/chrome/browser/extensions/api/declarative_content/content_condition.cc
index b2f91492..a56c7fb3 100644
--- a/chrome/browser/extensions/api/declarative_content/content_condition.cc
+++ b/chrome/browser/extensions/api/declarative_content/content_condition.cc
@@ -64,8 +64,9 @@
   for (const auto iter : api_condition_dict) {
     const std::string& predicate_name = iter.first;
     const base::Value& predicate_value = iter.second;
-    if (predicate_name == declarative_content_constants::kInstanceType)
+    if (predicate_name == declarative_content_constants::kInstanceType) {
       continue;
+    }
 
     const auto loc = predicate_factories.find(predicate_name);
     if (loc != predicate_factories.end())
@@ -76,8 +77,9 @@
       *error = base::StringPrintf(kUnknownConditionAttribute,
                                   predicate_name.c_str());
 
-    if (!error->empty())
+    if (!error->empty()) {
       return nullptr;
+    }
   }
 
   return std::make_unique<ContentCondition>(std::move(predicates));
diff --git a/chrome/browser/extensions/api/declarative_content/content_condition_unittest.cc b/chrome/browser/extensions/api/declarative_content/content_condition_unittest.cc
index e598f8a..af2fb89 100644
--- a/chrome/browser/extensions/api/declarative_content/content_condition_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_content/content_condition_unittest.cc
@@ -134,8 +134,9 @@
   ASSERT_EQ(1u, factory1.created_predicates().size());
   ASSERT_EQ(1u, factory2.created_predicates().size());
   std::vector<const ContentPredicate*> predicates;
-  for (const auto& predicate : condition->predicates)
+  for (const auto& predicate : condition->predicates) {
     predicates.push_back(predicate.get());
+  }
   EXPECT_THAT(predicates,
               UnorderedElementsAre(factory1.created_predicates()[0],
                                    factory2.created_predicates()[0]));
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
index 2b0105d..97bb2806 100644
--- a/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
+++ b/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
@@ -200,8 +200,9 @@
   ASSERT_TRUE(incognito_action);
 
   ASSERT_TRUE(ready.WaitUntilSatisfied());
-  if (is_enabled_in_incognito && mode == SPLIT)
+  if (is_enabled_in_incognito && mode == SPLIT) {
     ASSERT_TRUE(ready_incognito.WaitUntilSatisfied());
+  }
 
   const int incognito_tab_id = ExtensionTabUtil::GetTabId(incognito_tab);
 
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc
index 1ecdc8f..c5d2230d 100644
--- a/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc
+++ b/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc
@@ -155,14 +155,16 @@
       tracked_predicates_[group_predicates_pair.first].push_back(
           typed_predicate);
       for (const std::string& selector : typed_predicate->css_selectors()) {
-        if (watched_css_selector_predicate_count_[selector]++ == 0)
+        if (watched_css_selector_predicate_count_[selector]++ == 0) {
           watched_selectors_updated = true;
+        }
       }
     }
   }
 
-  if (watched_selectors_updated)
+  if (watched_selectors_updated) {
     UpdateRenderersWatchedCssSelectors(GetWatchedCssSelectors());
+  }
 }
 
 void DeclarativeContentCssConditionTracker::StopTrackingPredicates(
@@ -170,8 +172,9 @@
   bool watched_selectors_updated = false;
   for (const void* group : predicate_groups) {
     auto it = tracked_predicates_.find(group);
-    if (it == tracked_predicates_.end())
+    if (it == tracked_predicates_.end()) {
       continue;
+    }
     for (const DeclarativeContentCssPredicate* predicate : it->second) {
       for (const std::string& selector : predicate->css_selectors()) {
         auto loc = watched_css_selector_predicate_count_.find(selector);
@@ -185,8 +188,9 @@
     tracked_predicates_.erase(group);
   }
 
-  if (watched_selectors_updated)
+  if (watched_selectors_updated) {
     UpdateRenderersWatchedCssSelectors(GetWatchedCssSelectors());
+  }
 }
 
 void DeclarativeContentCssConditionTracker::TrackForWebContents(
@@ -274,8 +278,9 @@
     mojom::Renderer* renderer =
         RendererStartupHelperFactory::GetForBrowserContext(browser_context)
             ->GetRenderer(process);
-    if (renderer)
+    if (renderer) {
       renderer->WatchPages(watched_css_selectors);
+    }
   }
 }
 
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker.cc
index 73423fdb..dbb0f29 100644
--- a/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker.cc
+++ b/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker.cc
@@ -118,10 +118,12 @@
 UpdateState(bool request_evaluation_if_unchanged) {
   bool state_changed =
       IsCurrentUrlBookmarked() != is_url_bookmarked_;
-  if (state_changed)
+  if (state_changed) {
     is_url_bookmarked_ = !is_url_bookmarked_;
-  if (state_changed || request_evaluation_if_unchanged)
+  }
+  if (state_changed || request_evaluation_if_unchanged) {
     request_evaluation_.Run(web_contents());
+  }
 }
 
 bool DeclarativeContentIsBookmarkedConditionTracker::PerWebContentsTracker::
@@ -151,8 +153,9 @@
   bookmarks::BookmarkModel* bookmark_model =
       BookmarkModelFactory::GetForBrowserContext(context);
   // Can be null during unit test execution.
-  if (bookmark_model)
+  if (bookmark_model) {
     scoped_bookmarks_observation_.Observe(bookmark_model);
+  }
 }
 
 DeclarativeContentIsBookmarkedConditionTracker::
@@ -251,8 +254,9 @@
 
 void DeclarativeContentIsBookmarkedConditionTracker::
     ExtensiveBookmarkChangesEnded() {
-  if (--extensive_bookmark_changes_in_progress_ == 0)
+  if (--extensive_bookmark_changes_in_progress_ == 0) {
     UpdateAllPerWebContentsTrackers();
+  }
 }
 
 void DeclarativeContentIsBookmarkedConditionTracker::
@@ -262,8 +266,9 @@
 
 void DeclarativeContentIsBookmarkedConditionTracker::
     GroupedBookmarkChangesEnded() {
-  if (--extensive_bookmark_changes_in_progress_ == 0)
+  if (--extensive_bookmark_changes_in_progress_ == 0) {
     UpdateAllPerWebContentsTrackers();
+  }
 }
 
 void
@@ -275,8 +280,9 @@
 
 void DeclarativeContentIsBookmarkedConditionTracker::
 UpdateAllPerWebContentsTrackers() {
-  for (const auto& web_contents_tracker_pair : per_web_contents_tracker_)
+  for (const auto& web_contents_tracker_pair : per_web_contents_tracker_) {
     web_contents_tracker_pair.second->UpdateState(false);
+  }
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc
index 8eaf1080..c96d8df 100644
--- a/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc
@@ -38,8 +38,9 @@
     bool include_bookmarks) {
   base::ListValue permissions;
   permissions.Append("declarativeContent");
-  if (include_bookmarks)
+  if (include_bookmarks) {
     permissions.Append("bookmarks");
+  }
   return ExtensionBuilder()
       .SetManifest(base::DictValue()
                        .Set("name", "Test extension")
@@ -136,8 +137,10 @@
         page_is_bookmarked !=
         tracker_->EvaluatePredicate(is_not_bookmarked_predicate_.get(), tab);
 
-    if (is_bookmarked_predicate_success && is_not_bookmarked_predicate_success)
+    if (is_bookmarked_predicate_success &&
+        is_not_bookmarked_predicate_success) {
       return testing::AssertionSuccess();
+    }
 
     testing::AssertionResult result = testing::AssertionFailure();
     if (!is_bookmarked_predicate_success) {
@@ -147,8 +150,9 @@
     }
 
     if (!is_not_bookmarked_predicate_success) {
-      if (!is_bookmarked_predicate_success)
+      if (!is_bookmarked_predicate_success) {
         result << "; ";
+      }
       result << "IsBookmarkedPredicate(false): expected "
              << base::ToString(!page_is_bookmarked) << " got "
              << base::ToString(page_is_bookmarked);
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.cc
index e337cf4..4855c8a 100644
--- a/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.cc
+++ b/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.cc
@@ -51,8 +51,9 @@
   url_matcher_condition_set =
       url_matcher::URLMatcherFactory::CreateFromURLFilterDictionary(
           url_matcher_condition_factory, *dict, ++g_next_id, error);
-  if (!url_matcher_condition_set)
+  if (!url_matcher_condition_set) {
     return nullptr;
+  }
   return base::WrapUnique(new DeclarativeContentPageUrlPredicate(
       evaluator, url_matcher_condition_set));
 }
@@ -93,8 +94,9 @@
   std::set<base::MatcherStringPattern::ID> new_matches =
       url_matcher_->MatchURL(web_contents()->GetVisibleURL());
   matches_.swap(new_matches);
-  if (matches_ != new_matches || request_evaluation_if_unchanged)
+  if (matches_ != new_matches || request_evaluation_if_unchanged) {
     request_evaluation_.Run(web_contents());
+  }
 }
 
 void DeclarativeContentPageUrlConditionTracker::PerWebContentsTracker::
@@ -160,8 +162,9 @@
   std::vector<base::MatcherStringPattern::ID> condition_set_ids_to_remove;
   for (const void* group : predicate_groups) {
     auto loc = tracked_predicates_.find(group);
-    if (loc == tracked_predicates_.end())
+    if (loc == tracked_predicates_.end()) {
       continue;
+    }
     for (const DeclarativeContentPageUrlPredicate* predicate : loc->second) {
       condition_set_ids_to_remove.push_back(
           predicate->url_matcher_condition_set()->id());
@@ -223,8 +226,9 @@
 }
 
 void DeclarativeContentPageUrlConditionTracker::UpdateMatchesForAllTrackers() {
-  for (const auto& web_contents_tracker_pair : per_web_contents_tracker_)
+  for (const auto& web_contents_tracker_pair : per_web_contents_tracker_) {
     web_contents_tracker_pair.second->UpdateMatchesForCurrentUrl(false);
+  }
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/declarative_content/request_content_script_apitest.cc b/chrome/browser/extensions/api/declarative_content/request_content_script_apitest.cc
index 8da4e94..6fe0ff3e 100644
--- a/chrome/browser/extensions/api/declarative_content/request_content_script_apitest.cc
+++ b/chrome/browser/extensions/api/declarative_content/request_content_script_apitest.cc
@@ -119,8 +119,9 @@
     bool should_inject) {
   testing::AssertionResult result = CreateAndLoadExtension(manifest_permission,
                                                            script_matcher);
-  if (!result)
+  if (!result) {
     return result;
+  }
 
   // Setup listener for actual injection of script.
   ExtensionTestMessageListener injection_succeeded_listener(
@@ -128,15 +129,17 @@
   injection_succeeded_listener.set_extension_id(extension_->id());
 
   content::WebContents* web_contents = GetActiveWebContents();
-  if (!web_contents)
+  if (!web_contents) {
     return testing::AssertionFailure() << "No web contents.";
+  }
 
   EXPECT_TRUE(NavigateToURL(web_contents, embedded_test_server()->GetURL(
                                               "/extensions/test_file.html")));
 
   // Give the extension plenty of time to inject.
-  if (!RunAllPendingInRenderer(web_contents))
+  if (!RunAllPendingInRenderer(web_contents)) {
     return testing::AssertionFailure() << "Could not run pending in renderer.";
+  }
 
   // Make sure all running tasks are complete.
   content::RunAllPendingInMessageLoop();
@@ -176,8 +179,9 @@
                  kContentScriptSource);
 
   const Extension* extension = LoadExtension(dir->UnpackedPath());
-  if (!extension)
+  if (!extension) {
     return testing::AssertionFailure() << "Failed to load extension.";
+  }
 
   test_extension_dir_ = std::move(dir);
   extension_ = extension;
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
index dc8b1c5..f9d9608 100644
--- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -190,8 +190,9 @@
  private:
   // RulesMonitorService::TestObserver override:
   void OnRulesetLoadComplete(const ExtensionId& extension_id) override {
-    if (extension_id_ == extension_id)
+    if (extension_id_ == extension_id) {
       run_loop_.Quit();
+    }
   }
 
   const raw_ptr<RulesMonitorService> service_;
@@ -483,11 +484,13 @@
 
   void VerifyNavigations(const std::vector<GURL>& expected_blocked_urls,
                          const std::vector<GURL>& expected_allowed_urls) {
-    for (const GURL& url : expected_blocked_urls)
+    for (const GURL& url : expected_blocked_urls) {
       EXPECT_TRUE(IsNavigationBlocked(url)) << url;
+    }
 
-    for (const GURL& url : expected_allowed_urls)
+    for (const GURL& url : expected_allowed_urls) {
       EXPECT_FALSE(IsNavigationBlocked(url)) << url;
+    }
   }
 
   // TODO(crbug.com/40804030): Update function name to reflect it's used in
@@ -844,8 +847,9 @@
       DCHECK(url_to_wait_for_.is_empty());
       DCHECK(!wait_for_request_run_loop_);
 
-      if (requests_to_server_.count(url_to_wait_for))
+      if (requests_to_server_.count(url_to_wait_for)) {
         return;
+      }
       url_to_wait_for_ = url_to_wait_for;
       wait_for_request_run_loop_ = std::make_unique<base::RunLoop>();
     }
@@ -880,8 +884,9 @@
   }
 
   net::EmbeddedTestServer* https_server() {
-    if (!https_server_)
+    if (!https_server_) {
       InitializeHttpsServer();
+    }
 
     return https_server_.get();
   }
@@ -959,10 +964,11 @@
         base::FilePath crx_path = crx_dir.AppendASCII("temp.crx");
 
         base::FilePath pem_path;
-        if (is_extension_update)
+        if (is_extension_update) {
           pem_path = last_pem_path_;
-        else
+        } else {
           last_pem_path_ = crx_dir.AppendASCII("temp.pem");
+        }
 
         ASSERT_FALSE(base::PathExists(crx_dir));
         ASSERT_TRUE(base::CreateDirectory(crx_dir));
@@ -1189,10 +1195,11 @@
     TestRule rule = CreateGenericRule();
     rule.condition->url_filter.reset();
 
-    if (rule_data.is_regex_rule)
+    if (rule_data.is_regex_rule) {
       rule.condition->regex_filter = rule_data.filter;
-    else
+    } else {
       rule.condition->url_filter = rule_data.filter;
+    }
 
     rule.condition->resource_types = std::vector<std::string>({"main_frame"});
     rule.id = rule_data.id;
@@ -1352,8 +1359,9 @@
     rule.id = rule_data.id;
 
     // An empty list is not allowed for the "domains" property.
-    if (!rule_data.domains.empty())
+    if (!rule_data.domains.empty()) {
       rule.condition->domains = rule_data.domains;
+    }
 
     rule.condition->excluded_domains = rule_data.excluded_domains;
     rule.condition->resource_types = std::vector<std::string>({"sub_frame"});
@@ -1424,8 +1432,9 @@
     rule.id = rule_data.id;
 
     // An empty list is not allowed for the "request_domains" property.
-    if (!rule_data.request_domains.empty())
+    if (!rule_data.request_domains.empty()) {
       rule.condition->request_domains = rule_data.request_domains;
+    }
 
     rule.condition->excluded_request_domains =
         rule_data.excluded_request_domains;
@@ -2002,10 +2011,12 @@
     rule.condition->url_filter = rule_data.url_filter;
     rule.condition->resource_types = std::vector<std::string>({"main_frame"});
     rule.id = rule_data.id;
-    if (rule_data.add_to_first_extension)
+    if (rule_data.add_to_first_extension) {
       rules_1.push_back(rule);
-    if (rule_data.add_to_second_extension)
+    }
+    if (rule_data.add_to_second_extension) {
       rules_2.push_back(rule);
+    }
   }
 
   ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules(
@@ -2653,10 +2664,11 @@
 
     // Enable even indexed rulesets by default.
     bool enabled = i % 2 == 0;
-    if (enabled)
+    if (enabled) {
       expected_blocked_urls.push_back(GetURLForFilter(id));
-    else
+    } else {
       expected_allowed_urls.push_back(GetURLForFilter(id));
+    }
 
     rulesets.emplace_back(id, ToListValue(rules), enabled);
   }
@@ -3095,11 +3107,13 @@
 
   // Finally verify that all rulesets still work fine.
   std::vector<GURL> expected_blocked_urls;
-  for (int index : non_corrupted_ruleset_indices)
+  for (int index : non_corrupted_ruleset_indices) {
     expected_blocked_urls.push_back(urls_for_indices[index]);
+  }
 
-  for (int index : corrupted_ruleset_indices)
+  for (int index : corrupted_ruleset_indices) {
     expected_blocked_urls.push_back(urls_for_indices[index]);
+  }
 
   VerifyNavigations(expected_blocked_urls,
                     /*expected_allowed_urls=*/std::vector<GURL>());
@@ -3181,8 +3195,9 @@
 
   const int kNumStaticRulesets = 4;
   std::vector<TestRulesetInfo> rulesets;
-  for (int i = 0; i < kNumStaticRulesets; ++i)
+  for (int i = 0; i < kNumStaticRulesets; ++i) {
     rulesets.emplace_back(base::NumberToString(i), ToListValue({rule}));
+  }
 
   ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRulesets(
       rulesets, "extension_directory", {} /* hosts */));
@@ -3846,8 +3861,9 @@
 
     // The request will fail since it will be blocked by DNR.
     chrome.webRequest.onErrorOccurred.addListener(() => {
-      if (onBeforeRequestSeen)
+      if (onBeforeRequestSeen) {
         chrome.test.sendMessage('PASS');
+      }
     }, filter);
 
     chrome.test.sendMessage('INSTALLED');
@@ -5559,10 +5575,11 @@
       test_rule.priority = rule.priority;
       test_rule.action->type = rule.action_type;
       test_rule.condition->url_filter.reset();
-      if (rule.is_regex_rule)
+      if (rule.is_regex_rule) {
         test_rule.condition->regex_filter = rule.url_filter;
-      else
+      } else {
         test_rule.condition->url_filter = rule.url_filter;
+      }
       test_rule.condition->resource_types = rule.resource_types;
       test_rule.condition->request_methods = rule.request_methods;
       test_rules.push_back(test_rule);
@@ -6017,10 +6034,11 @@
       // The "resourceTypes" property (i.e. |rule.condition->resource_types|)
       // should not be an empty list. It should either be omitted or be a non-
       // empty list.
-      if (rule_data.resource_types.empty())
+      if (rule_data.resource_types.empty()) {
         rule.condition->resource_types = std::nullopt;
-      else
+      } else {
         rule.condition->resource_types = rule_data.resource_types;
+      }
 
       rule.condition->excluded_resource_types =
           rule_data.excluded_resource_types;
@@ -6571,8 +6589,9 @@
         helper.GetAllocatedGlobalRuleCount(extension_id, actual_rules_count);
 
     EXPECT_EQ(expected_rules_count.has_value(), has_allocated_rules_count);
-    if (expected_rules_count.has_value())
+    if (expected_rules_count.has_value()) {
       EXPECT_EQ(*expected_rules_count, actual_rules_count);
+    }
   }
 
   void VerifyKeepExcessAllocation(const ExtensionId& extension_id,
@@ -6894,8 +6913,9 @@
     rule.condition->url_filter = rule_data.url_filter;
 
     // An empty list is not allowed for the "requestMethods" property.
-    if (!rule_data.request_methods.empty())
+    if (!rule_data.request_methods.empty()) {
       rule.condition->request_methods = rule_data.request_methods;
+    }
 
     rule.condition->excluded_request_methods =
         rule_data.excluded_request_methods;
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc
index 3acab32..cd70a2b 100644
--- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc
@@ -419,8 +419,9 @@
 
     std::u16string error;
     std::vector<std::string> actual_ids;
-    for (const auto& val : result->GetList())
+    for (const auto& val : result->GetList()) {
       actual_ids.push_back(val.GetString());
+    }
 
     EXPECT_THAT(expected_ids, UnorderedElementsAreArray(actual_ids));
   }
@@ -546,8 +547,9 @@
         helper.GetAllocatedGlobalRuleCount(extension_id, actual_rules_count);
 
     EXPECT_EQ(expected_rules_count.has_value(), has_allocated_rules_count);
-    if (expected_rules_count.has_value())
+    if (expected_rules_count.has_value()) {
       EXPECT_EQ(*expected_rules_count, actual_rules_count);
+    }
   }
 
   void VerifyGetAvailableStaticRuleCountFunction(
@@ -639,12 +641,13 @@
   void LoadAndExpectSuccess(
       const std::optional<size_t>& expected_rules_count = std::nullopt) {
     size_t rules_count = 0;
-    if (expected_rules_count)
+    if (expected_rules_count) {
       rules_count = *expected_rules_count;
-    else if (rules_value_ && rules_value_->is_list())
+    } else if (rules_value_ && rules_value_->is_list()) {
       rules_count = rules_value_->GetList().size();
-    else
+    } else {
       rules_count = rules_list_.size();
+    }
 
     // We only index up to GetMaximumRulesPerRuleset() rules per ruleset.
     rules_count =
@@ -656,8 +659,9 @@
  private:
   // DeclarativeNetRequestUnittest override:
   void WriteExtensionData() override {
-    if (!rules_value_)
+    if (!rules_value_) {
       rules_value_ = base::Value(ToListValue(rules_list_));
+    }
 
     WriteManifestAndRuleset(
         extension_dir(),
@@ -1749,10 +1753,12 @@
   // Add 50 session-scoped regex rules, along with 10 non-regex rules.
   std::vector<TestRule> session_rules;
   int rule_id = kMinValidID;
-  for (size_t i = 0; i < 50; ++i)
+  for (size_t i = 0; i < 50; ++i) {
     session_rules.push_back(CreateRegexRule(rule_id++));
-  for (size_t i = 0; i < 10; ++i)
+  }
+  for (size_t i = 0; i < 10; ++i) {
     session_rules.push_back(CreateGenericRule(rule_id++));
+  }
 
   ASSERT_NO_FATAL_FAILURE(
       RunUpdateRulesFunction(*extension(), /*rule_ids_to_remove=*/{},
@@ -1844,8 +1850,9 @@
       rules.push_back(rule);
     }
 
-    for (size_t i = 0; i < num_regex_rules; ++i, ++id)
+    for (size_t i = 0; i < num_regex_rules; ++i, ++id) {
       rules.push_back(CreateRegexRule(id));
+    }
 
     return TestRulesetInfo(manifest_id_and_path, ToListValue(rules), enabled);
   }
@@ -1868,8 +1875,9 @@
       count = std::min(count, static_rule_limit);
 
       rules_count += count;
-      if (info.enabled)
+      if (info.enabled) {
         rules_enabled_count += count;
+      }
     }
 
     DeclarativeNetRequestUnittest::LoadAndExpectSuccess(
@@ -1905,8 +1913,9 @@
 TEST_P(MultipleRulesetsTest, EmptyRulesets) {
   size_t kNumRulesets = 7;
 
-  for (size_t i = 0; i < kNumRulesets; ++i)
+  for (size_t i = 0; i < kNumRulesets; ++i) {
     AddRuleset(CreateRuleset(base::NumberToString(i), 0, 0, true));
+  }
 
   LoadAndExpectSuccess();
 }
@@ -1977,8 +1986,9 @@
     std::vector<InstallWarning> warnings =
         GetFilteredInstallWarnings(*extension());
     std::vector<std::string> warning_strings;
-    for (const InstallWarning& warning : warnings)
+    for (const InstallWarning& warning : warnings) {
       warning_strings.push_back(warning.message);
+    }
 
     EXPECT_THAT(warning_strings, UnorderedElementsAreArray(expected_warnings));
   }
@@ -2103,8 +2113,9 @@
     bool enabled = i < kMaxEnabledRulesetCount - 1;
     std::string id = base::StringPrintf("%d.json", i);
     ruleset_ids.push_back(id);
-    if (enabled)
+    if (enabled) {
       expected_enabled_ruleset_ids.push_back(id);
+    }
     AddRuleset(CreateRuleset(id, 1, 1, enabled));
   }
 
diff --git a/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
index b65b1e5..9c4f410 100644
--- a/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
@@ -161,8 +161,9 @@
     info.render_process_id = kRendererId;
 
     net::HttpRequestHeaders extra_request_headers;
-    for (const auto& header : request_headers)
+    for (const auto& header : request_headers) {
       extra_request_headers.SetHeaderIfMissing(header, "foo");
+    }
 
     info.extra_request_headers = extra_request_headers;
     return info;
@@ -242,10 +243,12 @@
                                       "" /* extension_id */));
 
     // Remove the rulesets.
-    if (mask & kEnableRulesetOne)
+    if (mask & kEnableRulesetOne) {
       manager()->RemoveRuleset(extension_id_one);
-    if (mask & kEnableRulesetTwo)
+    }
+    if (mask & kEnableRulesetTwo) {
       manager()->RemoveRuleset(extension_id_two);
+    }
   }
 }
 
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
index 6089835..d07fb22 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
@@ -218,8 +218,9 @@
     rule.id = rule_id;
     rule.priority = 1;
     rule.actions.Append(std::move(action_dict));
-    for (auto* attribute : attributes)
+    for (auto* attribute : attributes) {
       rule.conditions.Append(CreateCondition(*attribute));
+    }
     return rule;
   }
 
@@ -282,8 +283,9 @@
   EXPECT_EQ(2u, matches.size());
 
   std::set<WebRequestRule::GlobalRuleId> matches_ids;
-  for (const auto* match : matches)
+  for (const auto* match : matches) {
     matches_ids.insert(match->id());
+  }
   EXPECT_TRUE(matches_ids.contains(std::make_pair(kExtensionId, kRuleId1)));
   EXPECT_TRUE(matches_ids.contains(std::make_pair(kExtensionId, kRuleId2)));
 
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
index f3ba2da3..94a7f29 100644
--- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
+++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
@@ -92,13 +92,15 @@
     const std::u16string& target_name) {
   DCHECK(!picker_controller_);
 
-  if (!render_frame_host->IsActive())
+  if (!render_frame_host->IsActive()) {
     return RespondNow(Error(kTargetNotActiveError));
+  }
 
   content::WebContents* web_contents =
       content::WebContents::FromRenderFrameHost(render_frame_host);
-  if (!web_contents)
+  if (!web_contents) {
     return RespondNow(Error(kTargetNotFoundError));
+  }
 
   gfx::NativeWindow parent_window = web_contents->GetTopLevelNativeWindow();
   // In case of coming from background extension page, |parent_window| will
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index fcd9782..3820314 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -50,8 +50,9 @@
   ~WebContentsTracker() override = default;
 
   void WebContentsDestroyed() override {
-    if (api_)
+    if (api_) {
       api_->web_contents_data_.erase(web_contents());
+    }
     delete this;
   }
 
@@ -112,8 +113,9 @@
   IdToPathMap& paths = data->allowed_unpacked_paths;
   auto existing =
       std::ranges::find(paths, path, &IdToPathMap::value_type::second);
-  if (existing != paths.end())
+  if (existing != paths.end()) {
     return existing->first;
+  }
 
   UnpackedRetryId id = base::Uuid::GenerateRandomV4().AsLowercaseString();
   paths[id] = path;
@@ -124,12 +126,14 @@
     content::WebContents* web_contents,
     const UnpackedRetryId& id) const {
   const WebContentsData* data = GetWebContentsData(web_contents);
-  if (!data)
+  if (!data) {
     return base::FilePath();
+  }
   const IdToPathMap& paths = data->allowed_unpacked_paths;
   auto path_iter = paths.find(id);
-  if (path_iter == paths.end())
+  if (path_iter == paths.end()) {
     return base::FilePath();
+  }
   return path_iter->second;
 }
 
@@ -163,8 +167,9 @@
 DeveloperPrivateAPI::GetOrCreateWebContentsData(
     content::WebContents* web_contents) {
   auto iter = web_contents_data_.find(web_contents);
-  if (iter != web_contents_data_.end())
+  if (iter != web_contents_data_.end()) {
     return &iter->second;
+  }
 
   // This is the first we've added this WebContents. Track its lifetime so we
   // can clean up the paths when it is destroyed.
diff --git a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
index 3500a88..8268922 100644
--- a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
+++ b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
@@ -138,8 +138,9 @@
                               is_incognito,
                               result);
   // Get app window views, if not incognito.
-  if (!is_incognito)
+  if (!is_incognito) {
     GetAppWindowViewsForExtension(extension, result);
+  }
   // Include a link to start the lazy background page, if applicable.
   bool include_lazy_background = true;
   // Don't include the lazy background page for incognito if the extension isn't
@@ -151,8 +152,9 @@
   }
 
   // Get inactive backgrounds.
-  if (!include_lazy_background || !is_enabled)
+  if (!include_lazy_background || !is_enabled) {
     return;
+  }
   if (BackgroundInfo::HasLazyBackgroundPage(&extension) &&
       !process_manager->GetBackgroundHostForExtension(extension.id())) {
     result->push_back(ConstructView(
@@ -191,8 +193,9 @@
     if (url.is_empty()) {
       ExtensionHost* extension_host =
           process_manager->GetBackgroundHostForRenderFrameHost(host);
-      if (extension_host)
+      if (extension_host) {
         url = extension_host->initial_url();
+      }
     }
 
     content::RenderProcessHost* process = host->GetProcess();
@@ -218,8 +221,9 @@
     ViewList* result) {
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   AppWindowRegistry* registry = AppWindowRegistry::Get(profile_);
-  if (!registry)
+  if (!registry) {
     return;
+  }
 
   AppWindowRegistry::AppWindowList windows =
       registry->GetAppWindowsForApp(extension.id());
@@ -230,8 +234,9 @@
     // If the window just opened, there might not be a committed (or visible)
     // url yet. In this case, use the initial url.
     GURL url = web_contents->GetLastCommittedURL();
-    if (url.is_empty())
+    if (url.is_empty()) {
       url = window->initial_url();
+    }
 
     content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame();
     result->push_back(
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index 72df629..e1add45 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -365,8 +365,9 @@
     const Extension* extension =
         ExtensionRegistry::Get(browser_context)
             ->GetExtensionById(by_ext->id(), ExtensionRegistry::EVERYTHING);
-    if (extension)
+    if (extension) {
       item.by_extension_name = extension->name();
+    }
   }
   // TODO(benjhayden): Implement fileSize.
   item.file_size = static_cast<double>(download_item->GetTotalBytes());
@@ -563,8 +564,9 @@
   DownloadManager* incognito_manager = nullptr;
   GetManagers(context, include_incognito, &manager, &incognito_manager);
   DownloadItem* download_item = manager->GetDownload(id);
-  if (!download_item && incognito_manager)
+  if (!download_item && incognito_manager) {
     download_item = incognito_manager->GetDownload(id);
+  }
   return download_item;
 }
 
@@ -613,8 +615,9 @@
   }
 
   for (std::string_view term_str : order_by_strs) {
-    if (term_str.empty())
+    if (term_str.empty()) {
       continue;
+    }
     DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING;
     if (term_str[0] == '-') {
       direction = DownloadQuery::DESCENDING;
@@ -681,8 +684,9 @@
   }
   if (query_in.order_by) {
     CompileDownloadQueryOrderBy(*query_in.order_by, error, &query_out);
-    if (!error->empty())
+    if (!error->empty()) {
       return;
+    }
   }
 
   for (const auto query_json_field : query_in.ToValue()) {
@@ -699,14 +703,17 @@
   DownloadQuery::DownloadVector all_items;
   if (query_in.id) {
     DownloadItem* download_item = manager->GetDownload(*query_in.id);
-    if (!download_item && incognito_manager)
+    if (!download_item && incognito_manager) {
       download_item = incognito_manager->GetDownload(*query_in.id);
-    if (download_item)
+    }
+    if (download_item) {
       all_items.push_back(download_item);
+    }
   } else {
     manager->GetAllDownloads(&all_items);
-    if (incognito_manager)
+    if (incognito_manager) {
       incognito_manager->GetAllDownloads(&all_items);
+    }
   }
   query_out.AddFilter(base::BindRepeating(&ShouldExport));
   query_out.Search(all_items.begin(), all_items.end(), results);
@@ -801,8 +808,9 @@
   void DetermineFilenameTimeout() { CallFilenameCallback(); }
 
   void CallFilenameCallback() {
-    if (!filename_changed_)
+    if (!filename_changed_) {
       return;
+    }
 
     std::move(filename_changed_)
         .Run(determined_filename_,
@@ -889,8 +897,9 @@
     for (auto& determiner : determiners_) {
       if (determiner.extension_id == extension_id) {
         found_info = true;
-        if (determiner.reported)
+        if (determiner.reported) {
           return false;
+        }
         determiner.reported = true;
         // Do not use filename if another determiner has already overridden the
         // filename and they take precedence. Extensions that were installed
@@ -904,16 +913,19 @@
               determiner.install_time, determiner_.extension_id,
               determiner_.install_time, &winner_extension_id,
               &determined_filename_, &determined_conflict_action_, &warnings);
-          if (!warnings.empty())
+          if (!warnings.empty()) {
             WarningService::NotifyWarningsOnUI(browser_context, warnings);
-          if (winner_extension_id == determiner.extension_id)
+          }
+          if (winner_extension_id == determiner.extension_id) {
             determiner_ = determiner;
+          }
         }
         break;
       }
     }
-    if (!found_info)
+    if (!found_info) {
       return false;
+    }
     CheckAllDeterminersCalled();
     return true;
   }
@@ -938,8 +950,9 @@
   // in that case, the callbacks will be null so they won't be Run.
   void CheckAllDeterminersCalled() {
     for (auto& determiner : determiners_) {
-      if (!determiner.reported)
+      if (!determiner.reported) {
         return;
+      }
     }
     CallFilenameCallback();
 
@@ -1019,8 +1032,9 @@
 }
 
 bool Fault(bool error, const char* message_in, std::string* message_out) {
-  if (!error)
+  if (!error) {
     return false;
+  }
   *message_out = message_in;
   return true;
 }
@@ -1123,8 +1137,9 @@
     }
   }
 
-  if (options.save_as)
+  if (options.save_as) {
     download_params->set_prompt(*options.save_as);
+  }
 
   if (options.headers) {
     for (const downloads::HeaderNameValuePair& header : *options.headers) {
@@ -1144,8 +1159,9 @@
   }
 
   std::string method_string = downloads::ToString(options.method);
-  if (!method_string.empty())
+  if (!method_string.empty()) {
     download_params->set_method(method_string);
+  }
   if (options.body) {
     download_params->set_post_body(
         network::ResourceRequestBody::CreateFromCopyOfBytes(
@@ -1223,8 +1239,9 @@
   DownloadQuery::DownloadVector results;
   std::string error;
   RunDownloadQuery(params->query, manager, incognito_manager, &error, &results);
-  if (!error.empty())
+  if (!error.empty()) {
     return RespondNow(Error(std::move(error)));
+  }
 
   base::ListValue json_results;
   for (DownloadManager::DownloadVector::const_iterator it = results.begin();
@@ -1303,8 +1320,10 @@
   EXTENSION_FUNCTION_VALIDATE(params);
   DownloadItem* download_item = GetDownload(
       browser_context(), include_incognito_information(), params->download_id);
-  if (download_item && (download_item->GetState() == DownloadItem::IN_PROGRESS))
+  if (download_item &&
+      (download_item->GetState() == DownloadItem::IN_PROGRESS)) {
     download_item->Cancel(true);
+  }
   // |download_item| can be NULL if the download ID was invalid or if the
   // download is not currently active.  Either way, it's not a failure.
   RecordApiFunctions(DownloadsFunctionName::kDownloadsFunctionCancel);
@@ -1326,8 +1345,9 @@
   DownloadQuery::DownloadVector results;
   std::string error;
   RunDownloadQuery(params->query, manager, incognito_manager, &error, &results);
-  if (!error.empty())
+  if (!error.empty()) {
     return RespondNow(Error(std::move(error)));
+  }
   base::ListValue json_results;
   for (download::DownloadItem* result : results) {
     json_results.Append(static_cast<int>(result->GetId()));
@@ -1478,8 +1498,9 @@
   DownloadItem* download_item = GetDownload(
       browser_context(), include_incognito_information(), params->download_id);
   std::string error;
-  if (InvalidId(download_item, &error))
+  if (InvalidId(download_item, &error)) {
     return RespondNow(Error(std::move(error)));
+  }
   download_item->ShowDownloadInShell();
   RecordApiFunctions(DownloadsFunctionName::kDownloadsFunctionShow);
   return RespondNow(NoArguments());
@@ -1734,8 +1755,9 @@
   DCHECK(icon_size == 16 || icon_size == 32);
   float scale = 1.0;
   content::WebContents* web_contents = GetSenderWebContents();
-  if (web_contents && web_contents->GetRenderWidgetHostView())
+  if (web_contents && web_contents->GetRenderWidgetHostView()) {
     scale = web_contents->GetRenderWidgetHostView()->GetDeviceScaleFactor();
+  }
   EXTENSION_FUNCTION_VALIDATE(icon_extractor_->ExtractIconURLForPath(
       download_item->GetTargetFilePath(), scale,
       IconLoaderSizeFromPixelSize(icon_size),
@@ -1770,8 +1792,9 @@
 ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   EventRouter* router = EventRouter::Get(profile_);
-  if (router)
+  if (router) {
     router->UnregisterObserver(this);
+  }
 }
 
 void ExtensionDownloadsEventRouter::SetDetermineFilenameTimeoutForTesting(
@@ -1784,8 +1807,9 @@
                                                  bool enabled) {
   auto iter = ui_disabling_extensions_.find(extension);
   if (iter == ui_disabling_extensions_.end()) {
-    if (!enabled)
+    if (!enabled) {
       ui_disabling_extensions_.insert(extension);
+    }
   } else if (enabled) {
     ui_disabling_extensions_.erase(extension);
   }
@@ -1934,24 +1958,27 @@
     const EventListenerInfo& details) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DownloadManager* manager = notifier_.GetManager();
-  if (!manager)
+  if (!manager) {
     return;
+  }
   bool determiner_removed =
       (details.event_name == downloads::OnDeterminingFilename::kEventName);
   EventRouter* router = EventRouter::Get(profile_);
   bool any_listeners =
       router->HasEventListener(downloads::OnChanged::kEventName) ||
       router->HasEventListener(downloads::OnDeterminingFilename::kEventName);
-  if (!determiner_removed && any_listeners)
+  if (!determiner_removed && any_listeners) {
     return;
+  }
   DownloadManager::DownloadVector items;
   manager->GetAllDownloads(&items);
   for (DownloadManager::DownloadVector::const_iterator iter = items.begin();
        iter != items.end(); ++iter) {
     ExtensionDownloadsEventRouterData* data =
         ExtensionDownloadsEventRouterData::Get(*iter);
-    if (!data)
+    if (!data) {
       continue;
+    }
     if (determiner_removed) {
       // Notify any items that may be waiting for callbacks from this
       // extension/determiner.  This will almost always be a no-op, however, it
@@ -1973,8 +2000,9 @@
     DownloadManager* manager,
     DownloadItem* download_item) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!ShouldExport(*download_item))
+  if (!ShouldExport(*download_item)) {
     return;
+  }
 
   EventRouter* router = EventRouter::Get(profile_);
   // Avoid allocating a bunch of memory in DownloadItemToJSON if it isn't going
@@ -2092,8 +2120,9 @@
     DownloadManager* manager,
     DownloadItem* download_item) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!ShouldExport(*download_item))
+  if (!ShouldExport(*download_item)) {
     return;
+  }
   DispatchEvent(events::DOWNLOADS_ON_ERASED, downloads::OnErased::kEventName,
                 true, Event::WillDispatchCallback(),
                 base::Value(static_cast<int>(download_item->GetId())));
@@ -2106,8 +2135,9 @@
     Event::WillDispatchCallback will_dispatch_callback,
     base::Value arg) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!EventRouter::Get(profile_))
+  if (!EventRouter::Get(profile_)) {
     return;
+  }
   base::ListValue args;
   args.Append(std::move(arg));
   // The downloads system wants to share on-record events with off-record
@@ -2135,19 +2165,22 @@
     UnloadedExtensionReason reason) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   auto iter = ui_disabling_extensions_.find(extension);
-  if (iter != ui_disabling_extensions_.end())
+  if (iter != ui_disabling_extensions_.end()) {
     ui_disabling_extensions_.erase(iter);
+  }
 }
 
 void ExtensionDownloadsEventRouter::CheckForHistoryFilesRemoval() {
   static const int kFileExistenceRateLimitSeconds = 10;
   DownloadManager* manager = notifier_.GetManager();
-  if (!manager)
+  if (!manager) {
     return;
+  }
   base::Time now(base::Time::Now());
   int delta = now.ToTimeT() - last_checked_removal_.ToTimeT();
-  if (delta <= kFileExistenceRateLimitSeconds)
+  if (delta <= kFileExistenceRateLimitSeconds) {
     return;
+  }
   last_checked_removal_ = now;
   manager->CheckForHistoryFilesRemoval();
 }
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index e74fc96..6aa155d 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -274,8 +274,9 @@
   void OnWillDispatchEvent(const extensions::Event& event) override {
     // TestObserver receives notifications for all events but only needs to
     // check download events.
-    if (!base::StartsWith(event.event_name, "downloads"))
+    if (!base::StartsWith(event.event_name, "downloads")) {
       return;
+    }
 
     Event* new_event = new Event(
         Profile::FromBrowserContext(event.restrict_to_browser_context),
@@ -493,8 +494,9 @@
   void GoOnTheRecord() {
     current_browser_ = browser_window_interface();
     current_profile_ = profile();
-    if (events_listener_.get())
+    if (events_listener_.get()) {
       events_listener_->UpdateProfile(current_profile());
+    }
   }
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -520,8 +522,9 @@
                                                false);
     current_browser_ = incognito_browser_;
     current_profile_ = incognito_profile_;
-    if (events_listener_.get())
+    if (events_listener_.get()) {
       events_listener_->UpdateProfile(current_profile());
+    }
   }
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
@@ -532,8 +535,9 @@
   bool WaitForInterruption(DownloadItem* item,
                            download::DownloadInterruptReason expected_error,
                            const std::string& on_created_event) {
-    if (!WaitFor(downloads::OnCreated::kEventName, on_created_event))
+    if (!WaitFor(downloads::OnCreated::kEventName, on_created_event)) {
       return false;
+    }
     // Now, onCreated is always fired before interruption.
     return WaitFor(
         downloads::OnChanged::kEventName,
@@ -649,8 +653,9 @@
 
     EXPECT_EQ(0, manager->BlockingShutdownCount());
     EXPECT_EQ(0, manager->InProgressCount());
-    if (manager->InProgressCount() != 0)
+    if (manager->InProgressCount() != 0) {
       return nullptr;
+    }
     return CreateSlowTestDownload(first_download_.get(), kFirstDownloadUrl);
   }
 
@@ -661,8 +666,9 @@
   DownloadItem* CreateSlowTestDownload(
       net::test_server::ControllableHttpResponse* response,
       const std::string& path) {
-    if (!embedded_test_server()->Started())
+    if (!embedded_test_server()->Started()) {
       StartEmbeddedTestServer();
+    }
     std::unique_ptr<content::DownloadTestObserver> observer(
         CreateInProgressDownloadObserver(1));
     DownloadManager* manager = GetCurrentManager();
@@ -963,8 +969,9 @@
   ~ScopedItemVectorCanceller() {
     for (DownloadManager::DownloadVector::const_iterator item = items_->begin();
          item != items_->end(); ++item) {
-      if ((*item)->GetState() == DownloadItem::IN_PROGRESS)
+      if ((*item)->GetState() == DownloadItem::IN_PROGRESS) {
         (*item)->Cancel(true);
+      }
       content::DownloadUpdatedObserver observer(
           (*item), base::BindRepeating(&ItemNotInProgress));
       observer.WaitForEvent();
diff --git a/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc b/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
index a54feb2f..39de6c5 100644
--- a/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
+++ b/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
@@ -52,11 +52,13 @@
   DWORD raw_type;
   encrypted_secret->clear();
   LONG result = key.Open(HKEY_CURRENT_USER, kDefaultRegistryPath, KEY_READ);
-  if (result != ERROR_SUCCESS)
+  if (result != ERROR_SUCCESS) {
     return result;
+  }
   result = key.ReadValue(kValueName, raw_data, &raw_data_size, &raw_type);
-  if (result != ERROR_SUCCESS)
+  if (result != ERROR_SUCCESS) {
     return result;
+  }
   if (raw_type != REG_BINARY) {
     key.DeleteValue(kValueName);
     return ERROR_INVALID_DATATYPE;
@@ -77,8 +79,9 @@
   DATA_BLOB output;
   BOOL result = ::CryptProtectData(&input, nullptr, nullptr, nullptr, nullptr,
                                    0, &output);
-  if (!result)
+  if (!result) {
     return ::GetLastError();
+  }
 
   // this does a copy
   ciphertext->assign(reinterpret_cast<std::string::value_type*>(output.pbData),
@@ -101,8 +104,9 @@
   BOOL result =
       ::CryptUnprotectData(&input, nullptr, nullptr, nullptr, nullptr, 0,
                            &output);
-  if (!result)
+  if (!result) {
     return ::GetLastError();
+  }
 
   plaintext->assign(reinterpret_cast<char*>(output.pbData), output.cbData);
   LocalFree(output.pbData);
@@ -117,17 +121,20 @@
 
   std::string encrypted_secret;
   LONG result = EncryptString(generated_secret, &encrypted_secret);
-  if (result != ERROR_SUCCESS)
+  if (result != ERROR_SUCCESS) {
     return result;
+  }
 
   base::win::RegKey key;
   result = key.Create(HKEY_CURRENT_USER, kDefaultRegistryPath, KEY_WRITE);
-  if (result != ERROR_SUCCESS)
+  if (result != ERROR_SUCCESS) {
     return result;
+  }
   result = key.WriteValue(kValueName, encrypted_secret.data(),
                           encrypted_secret.size(), REG_BINARY);
-  if (result == ERROR_SUCCESS)
+  if (result == ERROR_SUCCESS) {
     *secret = generated_secret;
+  }
   return result;
 }
 
@@ -150,10 +157,11 @@
   std::string password = base::Base64Encode(base::RandBytesAsVector(kBytes));
 
   OSStatus status = WriteKeychainItem(kServiceName, kAccountName, password);
-  if (status == noErr)
+  if (status == noErr) {
     *secret = password;
-  else
+  } else {
     secret->clear();
+  }
   return status;
 }
 
@@ -169,8 +177,9 @@
   OSStatus status;
   crypto::apple::ScopedKeychainUserInteractionAllowed user_interaction_allowed(
       FALSE, &status);
-  if (status != noErr)
+  if (status != noErr) {
     return status;
+  }
 
   base::AutoLock lock(crypto::apple::GetSecurityFrameworkLock());
   UInt32 password_length = 0;
@@ -258,8 +267,9 @@
 // Returns "AppData\Local\Google\Endpoint Verification".
 base::FilePath GetEndpointVerificationDir() {
   base::FilePath path;
-  if (!GetEndpointVerificationDirOverride()->empty())
+  if (!GetEndpointVerificationDirOverride()->empty()) {
     return *GetEndpointVerificationDirOverride();
+  }
 
   bool got_path = false;
 #if BUILDFLAG(IS_WIN)
@@ -272,8 +282,9 @@
 #elif BUILDFLAG(IS_MAC)
   got_path = base::PathService::Get(base::DIR_APP_DATA, &path);
 #endif
-  if (!got_path)
+  if (!got_path) {
     return path;
+  }
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
   path = path.AppendASCII("google");
@@ -329,8 +340,9 @@
   } else {
     // Not passing a second parameter means clear the data sored under |id|.
     success = base::DeleteFile(data_file);
-    if (base::IsDirectoryEmpty(data_file.DirName()))
+    if (base::IsDirectoryEmpty(data_file.DirName())) {
       base::DeleteFile(data_file.DirName());
+    }
   }
 
   std::move(callback).Run(success);
@@ -371,13 +383,15 @@
 #if BUILDFLAG(IS_WIN)
   std::string encrypted_secret;
   LONG result = ReadEncryptedSecret(&encrypted_secret);
-  if (result == ERROR_FILE_NOT_FOUND)
+  if (result == ERROR_FILE_NOT_FOUND) {
     result = CreateRandomSecret(&secret);
-  else if (result == ERROR_SUCCESS)
+  } else if (result == ERROR_SUCCESS) {
     result = DecryptString(encrypted_secret, &secret);
+  }
   // If something failed above [re]try creating the secret if forced.
-  if (result != ERROR_SUCCESS && force_recreate)
+  if (result != ERROR_SUCCESS && force_recreate) {
     result = CreateRandomSecret(&secret);
+  }
 #elif BUILDFLAG(IS_MAC)
   int32_t result = ReadEncryptedSecret(&secret, force_recreate);
 #else
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
index 7109ff2..dfbaf8c 100644
--- a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
+++ b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
@@ -100,8 +100,9 @@
   PopupHostWatcher& operator=(const PopupHostWatcher&) = delete;
 
   void Wait() {
-    if (created_ == destroyed_)
+    if (created_ == destroyed_) {
       return;
+    }
 
     base::RunLoop run_loop;
     quit_closure_ = run_loop.QuitClosure();
@@ -118,8 +119,9 @@
       content::BrowserContext* browser_context,
       ExtensionHost* host) override {
     // Only track lifetimes for popup window ExtensionHost instances.
-    if (host->extension_host_type() != mojom::ViewType::kExtensionPopup)
+    if (host->extension_host_type() != mojom::ViewType::kExtensionPopup) {
       return;
+    }
 
     ++created_;
     QuitIfSatisfied();
@@ -128,8 +130,9 @@
   void OnExtensionHostDestroyed(content::BrowserContext* browser_context,
                                 ExtensionHost* host) override {
     // Only track lifetimes for popup window ExtensionHost instances.
-    if (host->extension_host_type() != mojom::ViewType::kExtensionPopup)
+    if (host->extension_host_type() != mojom::ViewType::kExtensionPopup) {
       return;
+    }
 
     ++destroyed_;
     QuitIfSatisfied();
@@ -137,8 +140,9 @@
 
  private:
   void QuitIfSatisfied() {
-    if (!quit_closure_.is_null() && created_ == destroyed_)
+    if (!quit_closure_.is_null() && created_ == destroyed_) {
       quit_closure_.Run();
+    }
   }
 
   base::RepeatingClosure quit_closure_;
@@ -199,14 +203,16 @@
     // Setup the observer to wait for the popup to finish loading.
     content::CreateAndLoadWebContentsObserver frame_observer;
     std::unique_ptr<ExtensionTestMessageListener> listener;
-    if (!will_reply)
+    if (!will_reply) {
       listener = std::make_unique<ExtensionTestMessageListener>("ready");
+    }
     // Show first popup in first window and expect it to have loaded.
     ASSERT_TRUE(RunExtensionTest("browser_action/open_popup",
                                  {.extension_url = "open_popup_succeeds.html"}))
         << message_;
-    if (listener)
+    if (listener) {
       EXPECT_TRUE(listener->WaitUntilSatisfied());
+    }
     frame_observer.Wait();
     EnsurePopupActive();
   }
@@ -622,8 +628,9 @@
         size_to_wait_for_(size_to_wait_for) {}
 
   void Wait() {
-    if (current_size() != size_to_wait_for_)
+    if (current_size() != size_to_wait_for_) {
       run_loop_.Run();
+    }
   }
 
  private:
@@ -632,8 +639,9 @@
   }
 
   void PrimaryMainFrameWasResized(bool width_changed) override {
-    if (current_size() == size_to_wait_for_)
+    if (current_size() == size_to_wait_for_) {
       run_loop_.Quit();
+    }
   }
 
   gfx::Size size_to_wait_for_;
diff --git a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc
index 624aabf..6f10ef6 100644
--- a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc
+++ b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc
@@ -219,8 +219,9 @@
 ChromeFeedbackPrivateDelegate::GetLandingPageType(
     const feedback::FeedbackData& feedback_data) const {
   // Googlers using eve get a custom landing page.
-  if (!gaia::IsGoogleInternalAccountEmail(feedback_data.user_email()))
+  if (!gaia::IsGoogleInternalAccountEmail(feedback_data.user_email())) {
     return api::feedback_private::LandingPageType::kNormal;
+  }
 
   const std::vector<std::string> board =
       base::SplitString(base::SysInfo::GetLsbReleaseBoard(), "-",
@@ -234,8 +235,9 @@
     content::BrowserContext* context) const {
   auto* identity_manager = IdentityManagerFactory::GetForProfile(
       Profile::FromBrowserContext(context));
-  if (!identity_manager)
+  if (!identity_manager) {
     return std::string();
+  }
   // Browser sync consent is not required to use feedback.
   return identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin)
       .email;
diff --git a/chrome/browser/extensions/api/file_system/consent_provider_impl.cc b/chrome/browser/extensions/api/file_system/consent_provider_impl.cc
index 6870198..24b2756 100644
--- a/chrome/browser/extensions/api/file_system/consent_provider_impl.cc
+++ b/chrome/browser/extensions/api/file_system/consent_provider_impl.cc
@@ -199,8 +199,9 @@
 
   // If there is no web contents handle, then the method is most probably
   // executed from a background page.
-  if (!web_contents)
+  if (!web_contents) {
     web_contents = GetWebContentsForAppId(profile_, extension_id);
+  }
 
   if (!web_contents) {
     base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
@@ -230,8 +231,9 @@
     const std::string& volume_label,
     bool writable) {
   // Skip if |profile_| is gone.
-  if (!profile_)
+  if (!profile_) {
     return;
+  }
 
   ShowNotificationForAutoGrantedRequestFileSystem(profile_, extension_id,
                                                   extension_name, volume_id,
@@ -247,8 +249,9 @@
 bool ConsentProviderDelegate::IsAllowlistedComponent(
     const Extension& extension) {
   for (auto* allowlisted_id : kRequestFileSystemComponentAllowlist) {
-    if (extension.id().compare(allowlisted_id) == 0)
+    if (extension.id().compare(allowlisted_id) == 0) {
       return true;
+    }
   }
   return false;
 }
diff --git a/chrome/browser/extensions/api/file_system/file_system_api_unittest.cc b/chrome/browser/extensions/api/file_system/file_system_api_unittest.cc
index 197fd4d..4a8cb65 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api_unittest.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_api_unittest.cc
@@ -28,8 +28,9 @@
 void CheckExtensions(const std::vector<base::FilePath::StringType>& expected,
                      const std::vector<base::FilePath::StringType>& actual) {
   EXPECT_EQ(expected.size(), actual.size());
-  if (expected.size() != actual.size())
+  if (expected.size() != actual.size()) {
     return;
+  }
 
   for (size_t i = 0; i < expected.size(); ++i) {
     EXPECT_EQ(expected[i], actual[i]);
@@ -41,8 +42,9 @@
                                const std::string& extensions) {
   AcceptOption option;
 
-  if (!description.empty())
+  if (!description.empty()) {
     option.description = description;
+  }
 
   if (!mime_types.empty()) {
     option.mime_types = base::SplitString(
diff --git a/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc b/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
index 1480708..f0d706e9 100644
--- a/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
@@ -109,8 +109,9 @@
   // EventRouter::Observer overrides.
   void OnListenerAdded(const EventListenerInfo& details) override {
     // Call the callback only once, as the listener may be added multiple times.
-    if (details.extension_id != extension_id_ || !callback_)
+    if (details.extension_id != extension_id_ || !callback_) {
       return;
+    }
 
     base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
         FROM_HERE, std::move(callback_));
diff --git a/chrome/browser/extensions/api/font_settings/font_settings_api.cc b/chrome/browser/extensions/api/font_settings/font_settings_api.cc
index 69b4643..bc78774 100644
--- a/chrome/browser/extensions/api/font_settings/font_settings_api.cc
+++ b/chrome/browser/extensions/api/font_settings/font_settings_api.cc
@@ -79,8 +79,9 @@
   const char* script = fonts::ToString(script_enum);
   if (script[0] == 0)  // Empty string.
     result.append(prefs::kWebKitCommonScript);
-  else
+  else {
     result.append(script);
+  }
   return result;
 }
 
@@ -90,11 +91,13 @@
   // available.
   std::optional<std::string> localized_font_name =
       gfx::win::RetrieveLocalizedFontName(*font_name, "us-en");
-  if (!localized_font_name)
+  if (!localized_font_name) {
     localized_font_name = gfx::win::RetrieveLocalizedFontName(*font_name, "");
+  }
 
-  if (localized_font_name)
+  if (localized_font_name) {
     *font_name = std::move(localized_font_name.value());
+  }
 #endif  // BUILDFLAG(IS_WIN)
 }
 
@@ -262,8 +265,9 @@
 
 ExtensionFunction::ResponseAction FontSettingsClearFontFunction::Run() {
   Profile* profile = Profile::FromBrowserContext(browser_context());
-  if (profile->IsOffTheRecord())
+  if (profile->IsOffTheRecord()) {
     return RespondNow(Error(kSetFromIncognitoError));
+  }
 
   std::optional<fonts::ClearFont::Params> params =
       fonts::ClearFont::Params::Create(args());
@@ -316,8 +320,9 @@
 
 ExtensionFunction::ResponseAction FontSettingsSetFontFunction::Run() {
   Profile* profile = Profile::FromBrowserContext(browser_context());
-  if (profile->IsOffTheRecord())
+  if (profile->IsOffTheRecord()) {
     return RespondNow(Error(kSetFromIncognitoError));
+  }
 
   std::optional<fonts::SetFont::Params> params =
       fonts::SetFont::Params::Create(args());
@@ -380,8 +385,9 @@
 
 ExtensionFunction::ResponseAction ClearFontPrefExtensionFunction::Run() {
   Profile* profile = Profile::FromBrowserContext(browser_context());
-  if (profile->IsOffTheRecord())
+  if (profile->IsOffTheRecord()) {
     return RespondNow(Error(kSetFromIncognitoError));
+  }
 
   ExtensionPrefsHelper::Get(profile)->RemoveExtensionControlledPref(
       extension_id(), GetPrefName(), ChromeSettingScope::kRegular);
@@ -410,8 +416,9 @@
 
 ExtensionFunction::ResponseAction SetFontPrefExtensionFunction::Run() {
   Profile* profile = Profile::FromBrowserContext(browser_context());
-  if (profile->IsOffTheRecord())
+  if (profile->IsOffTheRecord()) {
     return RespondNow(Error(kSetFromIncognitoError));
+  }
 
   EXTENSION_FUNCTION_VALIDATE(args().size() >= 1);
   EXTENSION_FUNCTION_VALIDATE(args()[0].is_dict());
diff --git a/chrome/browser/extensions/api/gcm/extension_gcm_app_handler_unittest.cc b/chrome/browser/extensions/api/gcm/extension_gcm_app_handler_unittest.cc
index 8d9be31..4be7521 100644
--- a/chrome/browser/extensions/api/gcm/extension_gcm_app_handler_unittest.cc
+++ b/chrome/browser/extensions/api/gcm/extension_gcm_app_handler_unittest.cc
@@ -97,8 +97,9 @@
     base::WeakPtr<gcm::GCMProfileService> service,
     mojo::PendingReceiver<network::mojom::ProxyResolvingSocketFactory>
         receiver) {
-  if (!service)
+  if (!service) {
     return;
+  }
   network::mojom::NetworkContext* network_context =
       profile->GetDefaultStoragePartition()->GetNetworkContext();
   network_context->CreateProxyResolvingSocketFactory(std::move(receiver));
@@ -135,8 +136,9 @@
 
   // Signals that the asynchronous operation finishes.
   void SignalCompleted() {
-    if (run_loop_ && run_loop_->running())
+    if (run_loop_ && run_loop_->running()) {
       run_loop_->Quit();
+    }
   }
 
   // Runs until UI loop becomes idle.
@@ -212,8 +214,9 @@
 
   void RemoveAppHandler(const std::string& app_id) override {
     ExtensionGCMAppHandler::RemoveAppHandler(app_id);
-    if (GetGCMDriver()->app_handlers().empty())
+    if (GetGCMDriver()->app_handlers().empty()) {
       app_handler_count_drop_to_zero_ = true;
+    }
   }
 
   gcm::GCMClient::Result unregistration_result() const {
@@ -326,8 +329,9 @@
     waiter_.PumpUILoop();
     gcm_app_handler_->Shutdown();
     auto* partition = profile()->GetDefaultStoragePartition();
-    if (partition)
+    if (partition) {
       partition->WaitForDeletionTasksForTesting();
+    }
 
 #if BUILDFLAG(IS_CHROMEOS)
     gcm_app_handler_.reset();
diff --git a/chrome/browser/extensions/api/gcm/gcm_api.cc b/chrome/browser/extensions/api/gcm/gcm_api.cc
index 635940b..3a04879 100644
--- a/chrome/browser/extensions/api/gcm/gcm_api.cc
+++ b/chrome/browser/extensions/api/gcm/gcm_api.cc
@@ -184,8 +184,9 @@
   gcm::OutgoingMessage outgoing_message;
   outgoing_message.id = params->message.message_id;
   outgoing_message.data = params->message.data.additional_properties;
-  if (params->message.time_to_live)
+  if (params->message.time_to_live) {
     outgoing_message.time_to_live = *params->message.time_to_live;
+  }
 
   GetGCMDriver()->Send(
       extension()->id(), params->message.destination_id, outgoing_message,
@@ -232,8 +233,9 @@
                                  const gcm::IncomingMessage& message) {
   api::gcm::OnMessage::Message message_arg;
   message_arg.data.additional_properties = message.data;
-  if (!message.sender_id.empty())
+  if (!message.sender_id.empty()) {
     message_arg.from = message.sender_id;
+  }
   if (!message.collapse_key.empty()) {
     message_arg.collapse_key = message.collapse_key;
   }
diff --git a/chrome/browser/extensions/api/history/history_api.cc b/chrome/browser/extensions/api/history/history_api.cc
index 7abbef1d5..51da888 100644
--- a/chrome/browser/extensions/api/history/history_api.cc
+++ b/chrome/browser/extensions/api/history/history_api.cc
@@ -160,8 +160,9 @@
   removed.all_history = deletion_info.IsAllHistory();
 
   removed.urls.emplace();
-  for (const auto& row : deletion_info.deleted_rows())
+  for (const auto& row : deletion_info.deleted_rows()) {
     removed.urls->push_back(row.url().spec());
+  }
 
   auto args = OnVisitRemoved::Create(removed);
   DispatchEvent(profile_, events::HISTORY_ON_VISIT_REMOVED,
@@ -256,8 +257,9 @@
 
   GURL url;
   std::string error;
-  if (!ValidateUrl(params->details.url, &url, &error))
+  if (!ValidateUrl(params->details.url, &url, &error)) {
     return RespondNow(Error(std::move(error)));
+  }
 
   history::HistoryService* hs = HistoryServiceFactory::GetForProfile(
       GetProfile(), ServiceAccessType::EXPLICIT_ACCESS);
@@ -274,8 +276,9 @@
     history::QueryURLAndVisitsResult result) {
   VisitItemList visit_item_vec;
   if (result.success && !result.visits.empty()) {
-    for (const history::VisitRow& visit : result.visits)
+    for (const history::VisitRow& visit : result.visits) {
       visit_item_vec.push_back(GetVisitItem(visit));
+    }
   }
 
   Respond(ArgumentList(GetVisits::Results::Create(visit_item_vec)));
@@ -296,12 +299,15 @@
   options.policy_for_404_visits = history::VisitQuery404sPolicy::kExclude404s;
   options.include_actor_visits = true;
 
-  if (params->query.start_time)
+  if (params->query.start_time) {
     options.begin_time = GetTime(*params->query.start_time);
-  if (params->query.end_time)
+  }
+  if (params->query.end_time) {
     options.end_time = GetTime(*params->query.end_time);
-  if (params->query.max_results)
+  }
+  if (params->query.max_results) {
     options.max_count = *params->query.max_results;
+  }
 
   history::HistoryService* hs = HistoryServiceFactory::GetForProfile(
       GetProfile(), ServiceAccessType::EXPLICIT_ACCESS);
@@ -317,8 +323,9 @@
 void HistorySearchFunction::SearchComplete(history::QueryResults results) {
   HistoryItemList history_item_vec;
   if (!results.empty()) {
-    for (const auto& item : results)
+    for (const auto& item : results) {
       history_item_vec.push_back(GetHistoryItem(item));
+    }
   }
   Respond(ArgumentList(Search::Results::Create(history_item_vec)));
   Release();  // Balanced in Run().
@@ -330,8 +337,9 @@
 
   GURL url;
   std::string error;
-  if (!ValidateUrl(params->details.url, &url, &error))
+  if (!ValidateUrl(params->details.url, &url, &error)) {
     return RespondNow(Error(std::move(error)));
+  }
 
   history::HistoryService* hs = HistoryServiceFactory::GetForProfile(
       GetProfile(), ServiceAccessType::EXPLICIT_ACCESS);
@@ -345,12 +353,14 @@
   EXTENSION_FUNCTION_VALIDATE(params);
 
   std::string error;
-  if (!VerifyDeleteAllowed(&error))
+  if (!VerifyDeleteAllowed(&error)) {
     return RespondNow(Error(std::move(error)));
+  }
 
   GURL url;
-  if (!ValidateUrl(params->details.url, &url, &error))
+  if (!ValidateUrl(params->details.url, &url, &error)) {
     return RespondNow(Error(std::move(error)));
+  }
 
   history::HistoryService* hs = HistoryServiceFactory::GetForProfile(
       GetProfile(), ServiceAccessType::EXPLICIT_ACCESS);
@@ -377,8 +387,9 @@
   EXTENSION_FUNCTION_VALIDATE(params);
 
   std::string error;
-  if (!VerifyDeleteAllowed(&error))
+  if (!VerifyDeleteAllowed(&error)) {
     return RespondNow(Error(std::move(error)));
+  }
 
   base::Time start_time = GetTime(params->range.start_time);
   base::Time end_time = GetTime(params->range.end_time);
@@ -412,8 +423,9 @@
 
 ExtensionFunction::ResponseAction HistoryDeleteAllFunction::Run() {
   std::string error;
-  if (!VerifyDeleteAllowed(&error))
+  if (!VerifyDeleteAllowed(&error)) {
     return RespondNow(Error(std::move(error)));
+  }
 
   std::set<GURL> restrict_urls;
   history::HistoryService* hs = HistoryServiceFactory::GetForProfile(
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc
index 97feeb8a..be0967c8 100644
--- a/chrome/browser/extensions/api/identity/identity_api.cc
+++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -98,13 +98,15 @@
 void IdentityAPI::EraseStaleGaiaIdsForAllExtensions() {
   // Refresh tokens haven't been loaded yet. Wait for OnRefreshTokensLoaded() to
   // fire.
-  if (!identity_manager_->AreRefreshTokensLoaded())
+  if (!identity_manager_->AreRefreshTokensLoaded()) {
     return;
+  }
   auto accounts = GetAccountsWithRefreshTokensForExtensions();
   for (const ExtensionId& extension_id : extension_prefs_->GetExtensions()) {
     std::optional<GaiaId> gaia_id = GetGaiaIdForExtension(extension_id);
-    if (!gaia_id)
+    if (!gaia_id) {
       continue;
+    }
     if (!std::ranges::contains(accounts, *gaia_id, &CoreAccountInfo::gaia)) {
       EraseGaiaIdForExtension(extension_id);
     }
@@ -283,8 +285,9 @@
       events::IDENTITY_ON_SIGN_IN_CHANGED,
       api::identity::OnSignInChanged::kEventName, std::move(args), profile_));
 
-  if (on_signin_changed_callback_for_testing_)
+  if (on_signin_changed_callback_for_testing_) {
     on_signin_changed_callback_for_testing_.Run(event.get());
+  }
 
   event_router_->BroadcastEvent(std::move(event));
 }
diff --git a/chrome/browser/extensions/api/identity/identity_clear_all_cached_auth_tokens_function.cc b/chrome/browser/extensions/api/identity/identity_clear_all_cached_auth_tokens_function.cc
index 2b71f76..4d436d76 100644
--- a/chrome/browser/extensions/api/identity/identity_clear_all_cached_auth_tokens_function.cc
+++ b/chrome/browser/extensions/api/identity/identity_clear_all_cached_auth_tokens_function.cc
@@ -18,8 +18,9 @@
 ExtensionFunction::ResponseAction
 IdentityClearAllCachedAuthTokensFunction::Run() {
   Profile* profile = Profile::FromBrowserContext(browser_context());
-  if (profile->IsOffTheRecord())
+  if (profile->IsOffTheRecord()) {
     return RespondNow(Error(identity_constants::kOffTheRecord));
+  }
 
   IdentityAPI* id_api = IdentityAPI::GetFactoryInstance()->Get(profile);
   id_api->EraseGaiaIdForExtension(extension()->id());
diff --git a/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc b/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc
index 331dc6dd..ff77a04 100644
--- a/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc
+++ b/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc
@@ -92,8 +92,9 @@
 }
 
 IdentityLaunchWebAuthFlowFunction::~IdentityLaunchWebAuthFlowFunction() {
-  if (auth_flow_)
+  if (auth_flow_) {
     auth_flow_.release()->DetachDelegateAndDelete();
+  }
 }
 
 ExtensionFunction::ResponseAction IdentityLaunchWebAuthFlowFunction::Run() {
diff --git a/chrome/browser/extensions/api/identity/identity_mint_queue.cc b/chrome/browser/extensions/api/identity/identity_mint_queue.cc
index 063c9a2..013c34d 100644
--- a/chrome/browser/extensions/api/identity/identity_mint_queue.cc
+++ b/chrome/browser/extensions/api/identity/identity_mint_queue.cc
@@ -40,8 +40,9 @@
   request_queue.push_back(request);
   // If this is the first request, start it now. RequestComplete will start
   // all other requests.
-  if (request_queue.size() == 1)
+  if (request_queue.size() == 1) {
     RunRequest(type, request_queue);
+  }
 }
 
 void IdentityMintRequestQueue::RequestComplete(
@@ -53,8 +54,9 @@
   RequestQueue& request_queue = GetRequestQueueMap(type)[key];
   CHECK_EQ(request_queue.front(), request);
   request_queue.pop_front();
-  if (!request_queue.empty())
+  if (!request_queue.empty()) {
     RunRequest(type, request_queue);
+  }
 }
 
 void IdentityMintRequestQueue::RequestCancel(
diff --git a/chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.cc b/chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.cc
index cd8d79d..51ab679 100644
--- a/chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.cc
+++ b/chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.cc
@@ -18,8 +18,9 @@
     ~IdentityRemoveCachedAuthTokenFunction() = default;
 
 ExtensionFunction::ResponseAction IdentityRemoveCachedAuthTokenFunction::Run() {
-  if (Profile::FromBrowserContext(browser_context())->IsOffTheRecord())
+  if (Profile::FromBrowserContext(browser_context())->IsOffTheRecord()) {
     return RespondNow(Error(identity_constants::kOffTheRecord));
+  }
 
   std::optional<api::identity::RemoveCachedAuthToken::Params> params =
       api::identity::RemoveCachedAuthToken::Params::Create(args());
diff --git a/chrome/browser/extensions/api/identity/identity_token_cache.cc b/chrome/browser/extensions/api/identity/identity_token_cache.cc
index b0bd9500..39eb4e7 100644
--- a/chrome/browser/extensions/api/identity/identity_token_cache.cc
+++ b/chrome/browser/extensions/api/identity/identity_token_cache.cc
@@ -60,8 +60,9 @@
   time_to_live -= base::Minutes(20);
 
   base::TimeDelta zero_delta;
-  if (time_to_live < zero_delta)
+  if (time_to_live < zero_delta) {
     time_to_live = zero_delta;
+  }
 
   cache_value.expiration_time_ = base::Time::Now() + time_to_live;
   return cache_value;
@@ -69,8 +70,9 @@
 
 IdentityTokenCacheValue::CacheValueStatus IdentityTokenCacheValue::status()
     const {
-  if (is_expired())
+  if (is_expired()) {
     return IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND;
+  }
 
   return GetStatusInternal();
 }
@@ -151,8 +153,9 @@
 
 void IdentityTokenCache::SetToken(const ExtensionTokenKey& key,
                                   const IdentityTokenCacheValue& token_data) {
-  if (token_data.status() == IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND)
+  if (token_data.status() == IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND) {
     return;
+  }
 
   if (token_data.status() != IdentityTokenCacheValue::CACHE_STATUS_TOKEN) {
     const IdentityTokenCacheValue& cached_value = GetToken(key);
@@ -187,8 +190,9 @@
             return cached_token.token() == token;
           });
       if (num_erased > 0) {
-        if (cached_tokens.size() == 0)
+        if (cached_tokens.size() == 0) {
           access_tokens_cache_.erase(entry_it);
+        }
         // A token is in the cache at most once, so stop searching if erased.
         return;
       }
@@ -259,10 +263,11 @@
       return value.status() == IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND;
     });
 
-    if (cached_tokens.empty())
+    if (cached_tokens.empty()) {
       it = access_tokens_cache_.erase(it);
-    else
+    } else {
       ++it;
+    }
   }
 
   std::erase_if(intermediate_value_cache_, [](const auto& key_value_pair) {
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow.cc b/chrome/browser/extensions/api/identity/web_auth_flow.cc
index 7ce787b..03e3a9a 100644
--- a/chrome/browser/extensions/api/identity/web_auth_flow.cc
+++ b/chrome/browser/extensions/api/identity/web_auth_flow.cc
@@ -293,8 +293,9 @@
 }
 
 void WebAuthFlow::TitleWasSet(content::NavigationEntry* entry) {
-  if (delegate_)
+  if (delegate_) {
     delegate_->OnAuthFlowTitleChange(base::UTF16ToUTF8(entry->GetTitle()));
+  }
 }
 
 void WebAuthFlow::DidStopLoading() {
@@ -327,8 +328,9 @@
   // Websites may create and remove <iframe> during the auth flow. In
   // particular, to integrate CAPTCHA tests. Chrome shouldn't abort the auth
   // flow if a navigation failed in a sub-frame. https://crbug.com/1049565.
-  if (!navigation_handle->IsInPrimaryMainFrame())
+  if (!navigation_handle->IsInPrimaryMainFrame()) {
     return;
+  }
 
   if (delegate_) {
     delegate_->OnNavigationFinished(navigation_handle);
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow_browsertest.cc b/chrome/browser/extensions/api/identity/web_auth_flow_browsertest.cc
index 295a62d..a3283ee 100644
--- a/chrome/browser/extensions/api/identity/web_auth_flow_browsertest.cc
+++ b/chrome/browser/extensions/api/identity/web_auth_flow_browsertest.cc
@@ -88,8 +88,9 @@
           WebAuthFlow::AbortOnLoad::kYes,
       std::optional<base::TimeDelta> timeout_for_non_interactive = std::nullopt,
       std::optional<gfx::Rect> popup_bounds = std::nullopt) {
-    if (!profile)
+    if (!profile) {
       profile = GetProfile();
+    }
 
     web_auth_flow_ = std::make_unique<WebAuthFlow>(
         &mock_web_auth_flow_delegate_, profile, url, mode,
diff --git a/chrome/browser/extensions/api/idltest/idltest_api.cc b/chrome/browser/extensions/api/idltest/idltest_api.cc
index 59e6992..119acba3 100644
--- a/chrome/browser/extensions/api/idltest/idltest_api.cc
+++ b/chrome/browser/extensions/api/idltest/idltest_api.cc
@@ -19,8 +19,9 @@
     const base::Value::BlobStorage& input) {
   base::ListValue list;
   list.reserve(input.size());
-  for (int c : input)
+  for (int c : input) {
     list.Append(c);
+  }
   return base::Value(std::move(list));
 }
 
diff --git a/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc b/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc
index 654a7a0a..4df0b30 100644
--- a/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc
+++ b/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc
@@ -63,10 +63,11 @@
 
 void ImageWriterPrivateBaseFunction::OnComplete(bool success,
                                                 const std::string& error) {
-  if (success)
+  if (success) {
     Respond(NoArguments());
-  else
+  } else {
     Respond(Error(error));
+  }
 }
 
 ImageWriterPrivateWriteFromUrlFunction::
@@ -86,8 +87,9 @@
   }
 
   GURL url(params->image_url);
-  if (!url.is_valid())
+  if (!url.is_valid()) {
     return RespondNow(Error(image_writer::error::kUrlInvalid));
+  }
 
   std::string hash;
   if (params->options && params->options->image_hash) {
diff --git a/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc b/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc
index a54b391..2915921 100644
--- a/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc
+++ b/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc
@@ -89,8 +89,9 @@
 // static
 scoped_refptr<ImageWriterUtilityClient> ImageWriterUtilityClient::Create(
     const scoped_refptr<base::SequencedTaskRunner>& task_runner) {
-  if (g_factory_for_testing)
+  if (g_factory_for_testing) {
     return g_factory_for_testing->Run();
+  }
   return base::WrapRefCounted(new ImageWriterUtilityClient(task_runner));
 }
 
@@ -163,8 +164,9 @@
 void ImageWriterUtilityClient::BindServiceIfNeeded() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (removable_storage_writer_)
+  if (removable_storage_writer_) {
     return;
+  }
 
   content::ServiceProcessHost::Launch(
       removable_storage_writer_.BindNewPipeAndPassReceiver(),
@@ -184,22 +186,25 @@
 }
 
 void ImageWriterUtilityClient::OperationProgress(int64_t progress) {
-  if (progress_callback_)
+  if (progress_callback_) {
     progress_callback_.Run(progress);
+  }
 }
 
 void ImageWriterUtilityClient::OperationSucceeded() {
   SuccessCallback success_callback = std::move(success_callback_);
   ResetRequest();
-  if (success_callback)
+  if (success_callback) {
     std::move(success_callback).Run();
+  }
 }
 
 void ImageWriterUtilityClient::OperationFailed(const std::string& error) {
   ErrorCallback error_callback = std::move(error_callback_);
   ResetRequest();
-  if (error_callback)
+  if (error_callback) {
     std::move(error_callback).Run(error);
+  }
 }
 
 void ImageWriterUtilityClient::ResetRequest() {
diff --git a/chrome/browser/extensions/api/image_writer_private/operation.cc b/chrome/browser/extensions/api/image_writer_private/operation.cc
index d00e977..5b9e2ce0 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation.cc
@@ -201,8 +201,9 @@
 void Operation::SetStage(image_writer_api::Stage stage) {
   DCHECK(IsRunningInCorrectSequence());
 
-  if (IsCancelled())
+  if (IsCancelled()) {
     return;
+  }
 
   stage_ = stage;
   progress_ = 0;
@@ -294,8 +295,9 @@
     size_t bytes_total,
     base::OnceCallback<void(const std::string&)> callback) {
   DCHECK(IsRunningInCorrectSequence());
-  if (IsCancelled())
+  if (IsCancelled()) {
     return;
+  }
 
   CHECK_LE(bytes_processed, bytes_total);
 
@@ -343,8 +345,9 @@
 
 void Operation::CleanUp() {
   DCHECK(IsRunningInCorrectSequence());
-  for (base::OnceClosure& cleanup_function : cleanup_functions_)
+  for (base::OnceClosure& cleanup_function : cleanup_functions_) {
     std::move(cleanup_function).Run();
+  }
   cleanup_functions_.clear();
 }
 
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_manager.cc b/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
index 393c30ba..b0498808 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
@@ -214,8 +214,9 @@
 Operation* OperationManager::GetOperation(const ExtensionId& extension_id) {
   auto existing_operation = operations_.find(extension_id);
 
-  if (existing_operation == operations_.end())
+  if (existing_operation == operations_.end()) {
     return nullptr;
+  }
   return existing_operation->second.get();
 }
 
diff --git a/chrome/browser/extensions/api/image_writer_private/test_utils.cc b/chrome/browser/extensions/api/image_writer_private/test_utils.cc
index 742bc85..debf9dc 100644
--- a/chrome/browser/extensions/api/image_writer_private/test_utils.cc
+++ b/chrome/browser/extensions/api/image_writer_private/test_utils.cc
@@ -101,8 +101,9 @@
 
 void FakeImageWriterClient::SimulateProgressAndCompletion(
     const SimulateProgressInfo& info) {
-  for (int progress : info.progress_list)
+  for (int progress : info.progress_list) {
     Progress(progress);
+  }
   if (info.will_succeed) {
     Success();
   } else {
@@ -168,23 +169,27 @@
 }
 
 void FakeImageWriterClient::Progress(int64_t progress) {
-  if (!progress_callback_.is_null())
+  if (!progress_callback_.is_null()) {
     progress_callback_.Run(progress);
+  }
 }
 
 void FakeImageWriterClient::Success() {
-  if (!success_callback_.is_null())
+  if (!success_callback_.is_null()) {
     std::move(success_callback_).Run();
+  }
 }
 
 void FakeImageWriterClient::Error(const std::string& message) {
-  if (!error_callback_.is_null())
+  if (!error_callback_.is_null()) {
     std::move(error_callback_).Run(message);
+  }
 }
 
 void FakeImageWriterClient::Cancel() {
-  if (!cancel_callback_.is_null())
+  if (!cancel_callback_.is_null()) {
     std::move(cancel_callback_).Run();
+  }
 }
 
 #if !BUILDFLAG(IS_CHROMEOS)
@@ -212,8 +217,9 @@
   DCHECK(!client_.get())
       << "Single FakeImageWriterClient instance per test case expected.";
   client_ = client;
-  if (!client_creation_callback_.is_null())
+  if (!client_creation_callback_.is_null()) {
     std::move(client_creation_callback_).Run(client);
+  }
 }
 #endif
 
@@ -330,8 +336,9 @@
 
 bool GetTestDataDirectory(base::FilePath* path) {
   bool success = base::PathService::Get(chrome::DIR_TEST_DATA, path);
-  if (!success)
+  if (!success) {
     return false;
+  }
   *path = path->AppendASCII("image_writer_private");
   return true;
 }
diff --git a/chrome/browser/extensions/api/image_writer_private/zip_extractor.cc b/chrome/browser/extensions/api/image_writer_private/zip_extractor.cc
index 016e936e..79394d2 100644
--- a/chrome/browser/extensions/api/image_writer_private/zip_extractor.cc
+++ b/chrome/browser/extensions/api/image_writer_private/zip_extractor.cc
@@ -28,8 +28,9 @@
   base::File infile(image_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
                                     base::File::FLAG_WIN_EXCLUSIVE_WRITE |
                                     base::File::FLAG_WIN_SHARE_DELETE);
-  if (!infile.IsValid())
+  if (!infile.IsValid()) {
     return false;
+  }
 
   constexpr size_t kExpectedSize = sizeof(kExpectedMagic);
   std::array<unsigned char, kExpectedSize> actual_magic = {};
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api.cc b/chrome/browser/extensions/api/input_ime/input_ime_api.cc
index 2890558..0a28d51 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api.cc
@@ -80,8 +80,9 @@
 InputImeEventRouterFactory::~InputImeEventRouterFactory() = default;
 
 InputImeEventRouter* InputImeEventRouterFactory::GetRouter(Profile* profile) {
-  if (!profile)
+  if (!profile) {
     return nullptr;
+  }
   // The |router_map_| is keyed by the original profile.
   // Refers to the comments in |RemoveProfile| method for the reason.
   profile = profile->GetOriginalProfile();
@@ -101,8 +102,9 @@
 }
 
 void InputImeEventRouterFactory::RemoveProfile(Profile* profile) {
-  if (!profile || router_map_.empty())
+  if (!profile || router_map_.empty()) {
     return;
+  }
   auto it = router_map_.find(profile);
   // The routers are common between an incognito profile and its original
   // profile, and are keyed on the original profiles.
@@ -120,8 +122,9 @@
   std::string error;
   InputMethodEngine* engine = GetEngineIfActive(
       Profile::FromBrowserContext(browser_context()), extension_id(), &error);
-  if (!engine)
+  if (!engine) {
     return RespondNow(Error(InformativeError(error, static_function_name())));
+  }
 
   engine->KeyEventHandled(extension_id(), params->request_id, params->response);
   return RespondNow(NoArguments());
@@ -131,8 +134,9 @@
   std::string error;
   InputMethodEngine* engine = GetEngineIfActive(
       Profile::FromBrowserContext(browser_context()), extension_id(), &error);
-  if (!engine)
+  if (!engine) {
     return RespondNow(Error(InformativeError(error, static_function_name())));
+  }
 
   std::optional<SetComposition::Params> parent_params =
       SetComposition::Params::Create(args());
@@ -175,8 +179,9 @@
   std::string error;
   InputMethodEngine* engine = GetEngineIfActive(
       Profile::FromBrowserContext(browser_context()), extension_id(), &error);
-  if (!engine)
+  if (!engine) {
     return RespondNow(Error(InformativeError(error, static_function_name())));
+  }
 
   std::optional<CommitText::Params> parent_params =
       CommitText::Params::Create(args());
@@ -195,8 +200,9 @@
   std::string error;
   InputMethodEngine* engine = GetEngineIfActive(
       Profile::FromBrowserContext(browser_context()), extension_id(), &error);
-  if (!engine)
+  if (!engine) {
     return RespondNow(Error(InformativeError(error, static_function_name())));
+  }
 
   std::optional<SendKeyEvents::Params> parent_params =
       SendKeyEvents::Params::Create(args());
@@ -246,8 +252,9 @@
 }
 
 InputImeEventRouter* GetInputImeEventRouter(Profile* profile) {
-  if (!profile)
+  if (!profile) {
     return nullptr;
+  }
   return InputImeEventRouterFactory::GetInstance()->GetRouter(profile);
 }
 
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
index 915397f..198d14f5 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -86,8 +86,9 @@
 
   out->visible = input.visible ? *input.visible : true;
 
-  if (input.checked)
+  if (input.checked) {
     out->modified |= InputMethodEngine::MENU_ITEM_MODIFIED_CHECKED;
+  }
   out->checked = input.checked ? *input.checked : false;
 
   out->enabled = input.enabled ? *input.enabled : true;
@@ -152,16 +153,21 @@
 
 std::string GetKeyFromEvent(const ui::KeyEvent& event) {
   const std::string code = event.GetCodeString();
-  if (base::StartsWith(code, "Control", base::CompareCase::SENSITIVE))
+  if (base::StartsWith(code, "Control", base::CompareCase::SENSITIVE)) {
     return "Ctrl";
-  if (base::StartsWith(code, "Shift", base::CompareCase::SENSITIVE))
+  }
+  if (base::StartsWith(code, "Shift", base::CompareCase::SENSITIVE)) {
     return "Shift";
-  if (base::StartsWith(code, "Alt", base::CompareCase::SENSITIVE))
+  }
+  if (base::StartsWith(code, "Alt", base::CompareCase::SENSITIVE)) {
     return "Alt";
-  if (base::StartsWith(code, "Arrow", base::CompareCase::SENSITIVE))
+  }
+  if (base::StartsWith(code, "Arrow", base::CompareCase::SENSITIVE)) {
     return code.substr(5);
-  if (code == "Escape")
+  }
+  if (code == "Escape") {
     return "Esc";
+  }
   if (code == "Backspace" || code == "Tab" || code == "Enter" ||
       code == "CapsLock" || code == "Power")
     return code;
@@ -309,8 +315,9 @@
   void OnActivate(const std::string& component_id) override {
     // Don't check whether the extension listens on onActivate event here.
     // Send onActivate event to give the IME a chance to add their listeners.
-    if (extension_id_.empty())
+    if (extension_id_.empty()) {
       return;
+    }
 
     auto args(input_ime::OnActivate::Create(
         component_id, input_ime::ParseScreenType(GetCurrentScreenType())));
@@ -321,8 +328,9 @@
   }
 
   void OnBlur(const std::string& engine_id, int context_id) override {
-    if (extension_id_.empty() || !HasListener(input_ime::OnBlur::kEventName))
+    if (extension_id_.empty() || !HasListener(input_ime::OnBlur::kEventName)) {
       return;
+    }
 
     auto args(input_ime::OnBlur::Create(context_id));
 
@@ -333,8 +341,9 @@
   void OnKeyEvent(const std::string& component_id,
                   const ui::KeyEvent& event,
                   TextInputMethod::KeyEventDoneCallback callback) override {
-    if (extension_id_.empty())
+    if (extension_id_.empty()) {
       return;
+    }
 
     // If there is no listener for the event, no need to dispatch the event to
     // extension. Instead, releases the key event for default system behavior.
@@ -348,8 +357,9 @@
     std::string error;
     InputMethodEngine* engine =
         GetEngineIfActive(profile_, extension_id_, &error);
-    if (!engine)
+    if (!engine) {
       return;
+    }
     const std::string request_id =
         engine->AddPendingKeyEvent(component_id, std::move(callback));
 
@@ -388,8 +398,9 @@
   }
 
   void OnReset(const std::string& component_id) override {
-    if (extension_id_.empty() || !HasListener(input_ime::OnReset::kEventName))
+    if (extension_id_.empty() || !HasListener(input_ime::OnReset::kEventName)) {
       return;
+    }
 
     auto args(input_ime::OnReset::Create(component_id));
 
@@ -585,8 +596,9 @@
     if (extension_registry) {
       const extensions::Extension* extension =
           extension_registry->enabled_extensions().GetByID(extension_id_);
-      if (!extension)
+      if (!extension) {
         return;
+      }
       extensions::ProcessManager* process_manager =
           extensions::ProcessManager::Get(profile_);
       if (extensions::BackgroundInfo::HasBackgroundPage(extension) &&
@@ -634,8 +646,9 @@
             .GetEventListenersByName(input_ime::OnKeyEvent::kEventName);
     for (const std::unique_ptr<extensions::EventListener>& listener :
          listeners) {
-      if (listener->extension_id() == extension_id_ && !listener->IsLazy())
+      if (listener->extension_id() == extension_id_ && !listener->IsLazy()) {
         return true;
+      }
     }
     return false;
   }
@@ -680,8 +693,9 @@
 
   input_method_private::AutoCapitalizeType
   ConvertInputContextAutoCapitalizePrivate(ash::AutocapitalizationMode mode) {
-    if (!GetKeyboardConfig().auto_capitalize)
+    if (!GetKeyboardConfig().auto_capitalize) {
       return input_method_private::AutoCapitalizeType::kOff;
+    }
 
     switch (mode) {
       case ash::AutocapitalizationMode::kUnspecified:
@@ -819,8 +833,9 @@
   InputMethodEngine* engine =
       static_cast<InputMethodEngine*>(event_router->GetEngine(extension_id));
   DCHECK(engine) << kErrorEngineNotAvailable;
-  if (!engine)
+  if (!engine) {
     *error = kErrorEngineNotAvailable;
+  }
   return engine;
 }
 
@@ -834,8 +849,9 @@
     const std::vector<InputComponentInfo>& input_components) {
   VLOG(1) << "RegisterImeExtension: " << extension_id;
 
-  if (engine_map_[extension_id])
+  if (engine_map_[extension_id]) {
     return false;
+  }
 
   auto* manager = ash::input_method::InputMethodManager::Get();
   ash::ComponentExtensionIMEManager* comp_ext_ime_manager =
@@ -975,8 +991,9 @@
   std::string error;
   InputMethodEngine* engine = GetEngineIfActive(
       Profile::FromBrowserContext(browser_context()), extension_id(), &error);
-  if (!engine)
+  if (!engine) {
     return RespondNow(Error(InformativeError(error, static_function_name())));
+  }
   engine->HideInputView();
   return RespondNow(NoArguments());
 }
@@ -1004,8 +1021,9 @@
 
   engine->SetAssistiveWindowProperties(params.context_id, assistive_window,
                                        &error);
-  if (!error.empty())
+  if (!error.empty()) {
     return RespondNow(Error(InformativeError(error, static_function_name())));
+  }
   return RespondNow(WithArguments(true));
 }
 
@@ -1025,13 +1043,15 @@
 
   button.id = ConvertAssistiveWindowButtonId(params.button_id);
   button.window_type = ConvertAssistiveWindowType(params.window_type);
-  if (params.announce_string)
+  if (params.announce_string) {
     button.announce_string = base::UTF8ToUTF16(*params.announce_string);
+  }
 
   engine->SetButtonHighlighted(params.context_id, button, params.highlighted,
                                &error);
-  if (!error.empty())
+  if (!error.empty()) {
     return RespondNow(Error(InformativeError(error, static_function_name())));
+  }
 
   return RespondNow(NoArguments());
 }
@@ -1134,10 +1154,12 @@
     candidates_out.emplace_back();
     candidates_out.back().value = candidate_in.candidate;
     candidates_out.back().id = candidate_in.id;
-    if (candidate_in.label)
+    if (candidate_in.label) {
       candidates_out.back().label = *candidate_in.label;
-    if (candidate_in.annotation)
+    }
+    if (candidate_in.annotation) {
       candidates_out.back().annotation = *candidate_in.annotation;
+    }
     if (candidate_in.usage) {
       candidates_out.back().usage.title = candidate_in.usage->title;
       candidates_out.back().usage.body = candidate_in.usage->body;
@@ -1266,8 +1288,9 @@
   std::string error;
   InputMethodEngine* engine = GetEngineIfActive(
       Profile::FromBrowserContext(browser_context()), extension_id(), &error);
-  if (!engine)
+  if (!engine) {
     return RespondNow(Error(InformativeError(error, static_function_name())));
+  }
   std::optional<FinishComposingText::Params> parent_params =
       FinishComposingText::Params::Create(args());
   const FinishComposingText::Params::Parameters& params =
@@ -1298,8 +1321,9 @@
       // When extension is unloaded unexpectedly and reloaded, OS doesn't pass
       // details.browser_context value in OnListenerAdded callback. So we need
       // to reactivate engine here.
-      if (engine)
+      if (engine) {
         engine->Enable(engine->GetActiveComponentId());
+      }
       event_router->SetUnloadedExtensionId("");
     } else {
       event_router->RegisterImeExtension(extension->id(), *input_components);
@@ -1312,12 +1336,14 @@
                                       UnloadedExtensionReason reason) {
   const std::vector<InputComponentInfo>* input_components =
       InputComponents::GetInputComponents(extension);
-  if (!input_components || input_components->empty())
+  if (!input_components || input_components->empty()) {
     return;
+  }
   InputImeEventRouter* event_router =
       GetInputImeEventRouter(Profile::FromBrowserContext(browser_context));
-  if (!event_router)
+  if (!event_router) {
     return;
+  }
   auto* manager = ash::input_method::InputMethodManager::Get();
   ash::ComponentExtensionIMEManager* comp_ext_ime_manager =
       manager->GetComponentExtensionIMEManager();
@@ -1347,8 +1373,9 @@
 }
 
 void InputImeAPI::OnListenerAdded(const EventListenerInfo& details) {
-  if (details.is_lazy)
+  if (details.is_lazy) {
     return;
+  }
 
   // Other listeners may trigger this function, but only reactivate the IME
   // on focus event.
@@ -1361,25 +1388,29 @@
       GetEngineIfActive(Profile::FromBrowserContext(details.browser_context),
                         details.extension_id, &error);
   // Notifies the IME extension for IME ready with onActivate/onFocus events.
-  if (engine)
+  if (engine) {
     engine->Enable(engine->GetActiveComponentId());
+  }
 }
 
 void InputImeAPI::OnListenerRemoved(const EventListenerInfo& details) {
-  if (details.is_lazy)
+  if (details.is_lazy) {
     return;
+  }
 
   // If a key event listener was removed, cancel all the pending key events
   // because they might've been dropped by the IME.
-  if (details.event_name != input_ime::OnKeyEvent::kEventName)
+  if (details.event_name != input_ime::OnKeyEvent::kEventName) {
     return;
+  }
 
   std::string error;
   InputMethodEngine* engine =
       GetEngineIfActive(Profile::FromBrowserContext(details.browser_context),
                         details.extension_id, &error);
-  if (engine)
+  if (engine) {
     engine->CancelPendingKeyEvents();
+  }
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/instance_id/instance_id_api.cc b/chrome/browser/extensions/api/instance_id/instance_id_api.cc
index d5368d9..37c3e41 100644
--- a/chrome/browser/extensions/api/instance_id/instance_id_api.cc
+++ b/chrome/browser/extensions/api/instance_id/instance_id_api.cc
@@ -122,10 +122,11 @@
 void InstanceIDGetTokenFunction::GetTokenCompleted(
     const std::string& token,
     instance_id::InstanceID::Result result) {
-  if (result == instance_id::InstanceID::SUCCESS)
+  if (result == instance_id::InstanceID::SUCCESS) {
     Respond(WithArguments(token));
-  else
+  } else {
     Respond(Error(InstanceIDResultToError(result)));
+  }
 }
 
 InstanceIDDeleteTokenFunction::InstanceIDDeleteTokenFunction() = default;
@@ -148,10 +149,11 @@
 
 void InstanceIDDeleteTokenFunction::DeleteTokenCompleted(
     instance_id::InstanceID::Result result) {
-  if (result == instance_id::InstanceID::SUCCESS)
+  if (result == instance_id::InstanceID::SUCCESS) {
     Respond(NoArguments());
-  else
+  } else {
     Respond(Error(InstanceIDResultToError(result)));
+  }
 }
 
 InstanceIDDeleteIDFunction::InstanceIDDeleteIDFunction() = default;
@@ -167,10 +169,11 @@
 
 void InstanceIDDeleteIDFunction::DeleteIDCompleted(
     instance_id::InstanceID::Result result) {
-  if (result == instance_id::InstanceID::SUCCESS)
+  if (result == instance_id::InstanceID::SUCCESS) {
     Respond(NoArguments());
-  else
+  } else {
     Respond(Error(InstanceIDResultToError(result)));
+  }
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
index 70f069ab..a4a4ef2a 100644
--- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
+++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
@@ -545,8 +545,9 @@
       SpellcheckServiceFactory::GetForContext(browser_context());
   SpellcheckCustomDictionary* dictionary = service->GetCustomDictionary();
 
-  if (dictionary->IsLoaded())
+  if (dictionary->IsLoaded()) {
     return RespondNow(WithArguments(GetSpellcheckWords()));
+  }
 
   dictionary->AddObserver(this);
   AddRef();  // Balanced in OnCustomDictionaryLoaded().
@@ -692,8 +693,9 @@
   InputMethodUtil* util = manager->GetInputMethodUtil();
   scoped_refptr<InputMethodManager::State> ime_state =
       manager->GetActiveIMEState();
-  if (!ime_state.get())
+  if (!ime_state.get()) {
     return;
+  }
 
   const base::flat_set<std::string> enabled_ids(
       ime_state->GetEnabledInputMethodIds());
@@ -719,8 +721,9 @@
     if (enabled_ids.contains(input_method.id)) {
       input_method.enabled = true;
     }
-    if (descriptor.options_page_url().is_valid())
+    if (descriptor.options_page_url().is_valid()) {
       input_method.has_options_page = true;
+    }
     if (!allowed_ids.empty() && !allowed_ids.contains(input_method.id)) {
       input_method.is_prohibited_by_policy = true;
     }
@@ -786,8 +789,9 @@
   InputMethodManager* manager = InputMethodManager::Get();
   scoped_refptr<InputMethodManager::State> ime_state =
       manager->GetActiveIMEState();
-  if (!ime_state.get())
+  if (!ime_state.get()) {
     return RespondNow(NoArguments());
+  }
 
   std::string new_input_method_id = params->input_method_id;
   bool is_component_extension_ime =
@@ -858,8 +862,9 @@
   InputMethodManager* manager = InputMethodManager::Get();
   scoped_refptr<InputMethodManager::State> ime_state =
       manager->GetActiveIMEState();
-  if (!ime_state.get())
+  if (!ime_state.get()) {
     return RespondNow(NoArguments());
+  }
 
   std::string input_method_id = params->input_method_id;
   bool is_component_extension_ime =
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc
index 761afbc..9a1bc86d 100644
--- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc
@@ -462,8 +462,9 @@
 
     void GetInputMethodExtensions(
         input_method::InputMethodDescriptors* descriptors) override {
-      for (const auto& descriptor : input_methods_)
+      for (const auto& descriptor : input_methods_) {
         descriptors->push_back(descriptor);
+      }
     }
 
     input_method::InputMethodDescriptors input_methods_;
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc
index 700f307..2809680b7 100644
--- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc
+++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc
@@ -37,8 +37,9 @@
   // some unit tests try to create all context services, but don't initialize
   // the event router first.
   EventRouter* event_router = EventRouter::Get(context_);
-  if (!event_router)
+  if (!event_router) {
     return;
+  }
 
   event_router->RegisterObserver(this,
       language_settings_private::OnSpellcheckDictionariesChanged::kEventName);
@@ -73,16 +74,19 @@
 LanguageSettingsPrivateDelegate::GetHunspellDictionaryStatuses() {
   std::vector<language_settings_private::SpellcheckDictionaryStatus> statuses;
   for (const auto& dictionary : GetHunspellDictionaries()) {
-    if (!dictionary)
+    if (!dictionary) {
       continue;
+    }
     language_settings_private::SpellcheckDictionaryStatus status;
     status.language_code = dictionary->GetLanguage();
     status.is_ready = dictionary->IsReady();
     if (!status.is_ready) {
-      if (dictionary->IsDownloadInProgress())
+      if (dictionary->IsDownloadInProgress()) {
         status.is_downloading = true;
-      if (dictionary->IsDownloadFailure())
+      }
+      if (dictionary->IsDownloadFailure()) {
         status.download_failed = true;
+      }
     }
     statuses.push_back(std::move(status));
   }
@@ -94,8 +98,9 @@
   // event router, because some unit tests try to shutdown all context services,
   // but didn't initialize the event router first.
   EventRouter* event_router = EventRouter::Get(context_);
-  if (event_router)
+  if (event_router) {
     event_router->UnregisterObserver(this);
+  }
 
   if (listening_spellcheck_) {
     RemoveDictionaryObservers();
@@ -105,8 +110,9 @@
 #if BUILDFLAG(IS_CHROMEOS)
   if (listening_input_method_) {
     auto* input_method_manager = ash::input_method::InputMethodManager::Get();
-    if (input_method_manager)
+    if (input_method_manager) {
       input_method_manager->RemoveObserver(this);
+    }
     listening_input_method_ = false;
   }
 #endif  // BUILDFLAG(IS_CHROMEOS)
@@ -213,28 +219,32 @@
 
 void LanguageSettingsPrivateDelegate::RefreshDictionaries(bool was_listening,
                                                           bool should_listen) {
-  if (was_listening)
+  if (was_listening) {
     RemoveDictionaryObservers();
+  }
   hunspell_dictionaries_.clear();
   SpellcheckService* service = SpellcheckServiceFactory::GetForContext(
       context_);
-  if (!custom_dictionary_)
+  if (!custom_dictionary_) {
     custom_dictionary_ = service->GetCustomDictionary();
+  }
 
   const std::vector<std::unique_ptr<SpellcheckHunspellDictionary>>&
       dictionaries(service->GetHunspellDictionaries());
   for (const auto& dictionary : dictionaries) {
     hunspell_dictionaries_.push_back(dictionary->AsWeakPtr());
-    if (should_listen)
+    if (should_listen) {
       dictionary->AddObserver(this);
+    }
   }
 }
 
 const LanguageSettingsPrivateDelegate::WeakDictionaries&
 LanguageSettingsPrivateDelegate::GetHunspellDictionaries() {
   // If there are no hunspell dictionaries, or the first is invalid, refresh.
-  if (hunspell_dictionaries_.empty() || !hunspell_dictionaries_.front())
+  if (hunspell_dictionaries_.empty() || !hunspell_dictionaries_.front()) {
     RefreshDictionaries(listening_spellcheck_, listening_spellcheck_);
+  }
   return hunspell_dictionaries_;
 }
 
@@ -257,15 +267,17 @@
             &LanguageSettingsPrivateDelegate::OnSpellcheckDictionariesChanged,
             base::Unretained(this)));
     // Observe the dictionary of custom words.
-    if (custom_dictionary_)
+    if (custom_dictionary_) {
       custom_dictionary_->AddObserver(this);
+    }
   } else if (!should_listen && listening_spellcheck_) {
     // Stop observing any dictionaries that still exist.
     RemoveDictionaryObservers();
     hunspell_dictionaries_.clear();
     pref_change_registrar_.Remove(spellcheck::prefs::kSpellCheckDictionaries);
-    if (custom_dictionary_)
+    if (custom_dictionary_) {
       custom_dictionary_->RemoveObserver(this);
+    }
   }
 
   listening_spellcheck_ = should_listen;
@@ -283,10 +295,11 @@
 
   auto* input_method_manager = ash::input_method::InputMethodManager::Get();
   if (input_method_manager) {
-    if (should_listen && !listening_input_method_)
+    if (should_listen && !listening_input_method_) {
       input_method_manager->AddObserver(this);
-    else if (!should_listen && listening_input_method_)
+    } else if (!should_listen && listening_input_method_) {
       input_method_manager->RemoveObserver(this);
+    }
   }
 
   listening_input_method_ = should_listen;
@@ -324,8 +337,9 @@
 
 void LanguageSettingsPrivateDelegate::RemoveDictionaryObservers() {
   for (const auto& dictionary : hunspell_dictionaries_) {
-    if (dictionary)
+    if (dictionary) {
       dictionary->RemoveObserver(this);
+    }
   }
 }
 
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_unittest.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_unittest.cc
index ac31124..1fb1b68d 100644
--- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_unittest.cc
+++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_unittest.cc
@@ -90,8 +90,9 @@
       const std::string& language) override {}
   void OnHunspellDictionaryDownloadFailure(
       const std::string& language) override {
-    if (run_loop_)
+    if (run_loop_) {
       run_loop_->Quit();
+    }
   }
 
 #if BUILDFLAG(IS_WIN)
diff --git a/chrome/browser/extensions/api/management/management_api_browsertest.cc b/chrome/browser/extensions/api/management/management_api_browsertest.cc
index 29ef6ec5..642056d 100644
--- a/chrome/browser/extensions/api/management/management_api_browsertest.cc
+++ b/chrome/browser/extensions/api/management/management_api_browsertest.cc
@@ -82,8 +82,9 @@
     ExtensionHost* background_host =
         ProcessManager::Get(profile())->GetBackgroundHostForExtension(
             extension_id);
-    if (!background_host)
+    if (!background_host) {
       return false;
+    }
     content::CrashTab(background_host->host_contents());
     return true;
   }
@@ -376,8 +377,9 @@
     scoped_refptr<ManagementSetEnabledFunction> function(
         new ManagementSetEnabledFunction);
     function->set_extension(extension);
-    if (user_gesture)
+    if (user_gesture) {
       function->set_user_gesture(true);
+    }
     function->SetRenderFrameHost(GetActiveWebContents()->GetPrimaryMainFrame());
     bool response = test_utils::RunFunction(
         function.get(),
diff --git a/chrome/browser/extensions/api/management/management_apitest.cc b/chrome/browser/extensions/api/management/management_apitest.cc
index 9df4534..dae1080 100644
--- a/chrome/browser/extensions/api/management/management_apitest.cc
+++ b/chrome/browser/extensions/api/management/management_apitest.cc
@@ -139,8 +139,9 @@
     ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(app_path),
                               {.context_type = ContextType::kFromManifest}));
 
-    if (out_app_id)
+    if (out_app_id) {
       *out_app_id = last_loaded_extension_id();
+    }
 
     ASSERT_TRUE(launched_app.WaitUntilSatisfied());
   }
diff --git a/chrome/browser/extensions/api/management/management_browsertest.cc b/chrome/browser/extensions/api/management/management_browsertest.cc
index 54629c9..0e7ab10 100644
--- a/chrome/browser/extensions/api/management/management_browsertest.cc
+++ b/chrome/browser/extensions/api/management/management_browsertest.cc
@@ -165,8 +165,9 @@
     extensions::ExtensionHost* ext_host =
         manager->GetBackgroundHostForExtension(extension->id());
     EXPECT_TRUE(ext_host);
-    if (!ext_host)
+    if (!ext_host) {
       return false;
+    }
 
     std::string version_from_bg =
         content::EvalJs(ext_host->host_contents(), "version()").ExtractString();
diff --git a/chrome/browser/extensions/api/messaging/chrome_messaging_delegate.cc b/chrome/browser/extensions/api/messaging/chrome_messaging_delegate.cc
index 817cbbf9..0acbfa8 100644
--- a/chrome/browser/extensions/api/messaging/chrome_messaging_delegate.cc
+++ b/chrome/browser/extensions/api/messaging/chrome_messaging_delegate.cc
@@ -45,13 +45,16 @@
   PolicyPermission allow_result = PolicyPermission::ALLOW_ALL;
   if (pref_service->IsManagedPreference(
           pref_names::kNativeMessagingUserLevelHosts)) {
-    if (!pref_service->GetBoolean(pref_names::kNativeMessagingUserLevelHosts))
+    if (!pref_service->GetBoolean(pref_names::kNativeMessagingUserLevelHosts)) {
       allow_result = PolicyPermission::ALLOW_SYSTEM_ONLY;
+    }
   }
 
   // All native messaging hosts are allowed if there is no blocklist.
-  if (!pref_service->IsManagedPreference(pref_names::kNativeMessagingBlocklist))
+  if (!pref_service->IsManagedPreference(
+          pref_names::kNativeMessagingBlocklist)) {
     return allow_result;
+  }
   const base::ListValue& blocklist =
       pref_service->GetList(pref_names::kNativeMessagingBlocklist);
 
@@ -123,8 +126,9 @@
   std::unique_ptr<NativeMessageHost> native_host =
       NativeMessageHost::Create(browser_context, native_view, extension_id,
                                 native_app_name, allow_user_level, error_out);
-  if (!native_host.get())
+  if (!native_host.get()) {
     return nullptr;
+  }
   return std::make_unique<NativeMessagePort>(channel_delegate, receiver_port_id,
                                              std::move(native_host));
 }
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host.cc b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
index c6f05c6..f378c3f 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
@@ -182,8 +182,9 @@
 void NativeMessageProcessHost::OnMessage(const std::string& json) {
   DCHECK(task_runner_->BelongsToCurrentThread());
 
-  if (closed_)
+  if (closed_) {
     return;
+  }
 
   // Allocate new buffer for the message.
   scoped_refptr<net::IOBufferWithSize> buffer =
@@ -208,8 +209,9 @@
   // Send() may be called before the host process is started. In that case the
   // message will be written when OnHostProcessLaunched() is called. If it's
   // already started then write the message now.
-  if (write_stream_)
+  if (write_stream_) {
     DoWrite();
+  }
 }
 
 void NativeMessageProcessHost::Start(Client* client) {
@@ -227,8 +229,9 @@
 }
 
 void NativeMessageProcessHost::WaitRead() {
-  if (closed_)
+  if (closed_) {
     return;
+  }
 
   DCHECK(!read_pending_);
 
@@ -273,8 +276,9 @@
     base::expected<base::ByteSize, net::Error> result) {
   DCHECK(task_runner_->BelongsToCurrentThread());
 
-  if (closed_)
+  if (closed_) {
     return;
+  }
 
   if (result.has_value()) {
     if (result->is_positive()) {
@@ -301,8 +305,9 @@
   incoming_data_.append(data, data_size);
 
   while (true) {
-    if (incoming_data_.size() < kMessageHeaderSize)
+    if (incoming_data_.size() < kMessageHeaderSize) {
       return;
+    }
 
     // TODO(crbug.com/428945428): Fix unsafe uses of std::string::data().
     size_t message_size =
@@ -315,8 +320,9 @@
       return;
     }
 
-    if (incoming_data_.size() < message_size + kMessageHeaderSize)
+    if (incoming_data_.size() < message_size + kMessageHeaderSize) {
       return;
+    }
 
     client_->PostMessageFromNativeHost(
         incoming_data_.substr(kMessageHeaderSize, message_size));
@@ -331,8 +337,9 @@
   while (!write_pending_ && !closed_) {
     if (!current_write_buffer_.get() ||
         !current_write_buffer_->BytesRemaining()) {
-      if (write_queue_.empty())
+      if (write_queue_.empty()) {
         return;
+      }
       scoped_refptr<net::IOBufferWithSize> buffer =
           std::move(write_queue_.front());
       int buffer_size = buffer->size();
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
index e1f478e..98046a6 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
@@ -162,14 +162,16 @@
       last_message_parsed_ = std::move(*dict_value).TakeDict();
     }
 
-    if (run_loop_)
+    if (run_loop_) {
       run_loop_->Quit();
+    }
   }
 
   void CloseChannel(const std::string& error_message) override {
     channel_closed_ = true;
-    if (run_loop_)
+    if (run_loop_) {
       run_loop_->Quit();
+    }
   }
 
  protected:
@@ -180,12 +182,14 @@
 
   base::FilePath CreateTempFileWithMessage(const std::string& message) {
     base::FilePath filename;
-    if (!base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &filename))
+    if (!base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &filename)) {
       return base::FilePath();
+    }
 
     std::string message_with_header = FormatMessage(message);
-    if (!base::WriteFile(filename, message_with_header))
+    if (!base::WriteFile(filename, message_with_header)) {
       return base::FilePath();
+    }
 
     return filename;
   }
@@ -283,8 +287,9 @@
   base::TimeTicks start_time = base::TimeTicks::Now();
   while (base::TimeTicks::Now() - start_time < TestTimeouts::action_timeout()) {
     ASSERT_TRUE(base::ReadFileToString(temp_output_file, &output));
-    if (!output.empty())
+    if (!output.empty()) {
       break;
+    }
     base::PlatformThread::YieldCurrentThread();
   }
 
diff --git a/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc b/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc
index bdf1297e..7487061 100644
--- a/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc
+++ b/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc
@@ -144,8 +144,9 @@
 
  protected:
   bool RunTest(const char* extension_name) {
-    if (GetParam() == ContextType::kPersistentBackground)
+    if (GetParam() == ContextType::kPersistentBackground) {
       return RunExtensionTest(extension_name);
+    }
     std::string lazy_extension_name = base::StrCat({extension_name, "/lazy"});
     return RunExtensionTest(lazy_extension_name.c_str());
   }
diff --git a/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc b/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc
index 2197409..e0251b7 100644
--- a/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc
+++ b/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc
@@ -23,8 +23,9 @@
 bool NativeMessagingHostListPolicyHandler::CheckListEntry(
     const base::Value& value) {
   const std::string& str = value.GetString();
-  if (allow_wildcards_ && str == "*")
+  if (allow_wildcards_ && str == "*") {
     return true;
+  }
 
   return NativeMessagingHostManifest::IsValidName(str);
 }
diff --git a/chrome/browser/extensions/api/notifications/extension_notification_display_helper.cc b/chrome/browser/extensions/api/notifications/extension_notification_display_helper.cc
index 6e16cd1..128c68b 100644
--- a/chrome/browser/extensions/api/notifications/extension_notification_display_helper.cc
+++ b/chrome/browser/extensions/api/notifications/extension_notification_display_helper.cc
@@ -39,8 +39,9 @@
 ExtensionNotificationDisplayHelper::GetByNotificationId(
     const std::string& notification_id) {
   for (const auto& notification : notifications_) {
-    if (notification->id() == notification_id)
+    if (notification->id() == notification_id) {
       return notification.get();
+    }
   }
 
   return nullptr;
@@ -51,8 +52,9 @@
     const GURL& extension_origin) const {
   std::set<std::string> notification_ids;
   for (const auto& notification : notifications_) {
-    if (notification->origin_url() == extension_origin)
+    if (notification->origin_url() == extension_origin) {
       notification_ids.insert(notification->id());
+    }
   }
 
   return notification_ids;
@@ -63,8 +65,9 @@
   auto iter = std::ranges::find(notifications_, notification_id,
                                 &message_center::Notification::id);
 
-  if (iter == notifications_.end())
+  if (iter == notifications_.end()) {
     return false;
+  }
 
   notifications_.erase(iter);
   return true;
@@ -72,8 +75,9 @@
 
 bool ExtensionNotificationDisplayHelper::Close(
     const std::string& notification_id) {
-  if (!EraseDataForNotificationId(notification_id))
+  if (!EraseDataForNotificationId(notification_id)) {
     return false;
+  }
 
   GetDisplayService()->Close(NotificationHandler::Type::EXTENSION,
                              notification_id);
diff --git a/chrome/browser/extensions/api/notifications/extension_notification_handler.cc b/chrome/browser/extensions/api/notifications/extension_notification_handler.cc
index 4d0e4cba..89c60f2 100644
--- a/chrome/browser/extensions/api/notifications/extension_notification_handler.cc
+++ b/chrome/browser/extensions/api/notifications/extension_notification_handler.cc
@@ -72,8 +72,9 @@
 
   ExtensionNotificationDisplayHelper* display_helper =
       ExtensionNotificationDisplayHelperFactory::GetForProfile(profile);
-  if (display_helper)
+  if (display_helper) {
     display_helper->EraseDataForNotificationId(notification_id);
+  }
 
   std::move(completed_closure).Run();
 }
@@ -89,8 +90,9 @@
 
   ExtensionId extension_id(GetExtensionId(GURL(origin)));
   base::ListValue args = CreateBaseEventArgs(extension_id, notification_id);
-  if (action_index.has_value())
+  if (action_index.has_value()) {
     args.Append(action_index.value());
+  }
   events::HistogramValue histogram_value =
       action_index.has_value() ? events::NOTIFICATIONS_ON_BUTTON_CLICKED
                                : events::NOTIFICATIONS_ON_CLICKED;
@@ -129,12 +131,14 @@
     const std::string& event_name,
     EventRouter::UserGestureState user_gesture,
     base::ListValue args) {
-  if (extension_id.empty())
+  if (extension_id.empty()) {
     return;
+  }
 
   EventRouter* event_router = EventRouter::Get(profile);
-  if (!event_router)
+  if (!event_router) {
     return;
+  }
 
   auto event =
       std::make_unique<Event>(histogram_value, event_name, std::move(args));
diff --git a/chrome/browser/extensions/api/notifications/notifications_api.cc b/chrome/browser/extensions/api/notifications/notifications_api.cc
index 34af87e..dc76b95 100644
--- a/chrome/browser/extensions/api/notifications/notifications_api.cc
+++ b/chrome/browser/extensions/api/notifications/notifications_api.cc
@@ -136,8 +136,9 @@
   const size_t rgba_data_length = rgba_data.size();
   const size_t rgba_area = width * height;
 
-  if (rgba_data_length != rgba_area * kBytesPerPixel)
+  if (rgba_data_length != rgba_area * kBytesPerPixel) {
     return false;
+  }
 
   SkBitmap bitmap;
   // Allocate the actual backing store with the sanitized dimensions.
@@ -147,8 +148,9 @@
   bitmap.setPixels(&pixels[0]);
 
   // Ensure that our bitmap and our data now refer to the same number of pixels.
-  if (rgba_data_length != bitmap.computeByteSize())
+  if (rgba_data_length != bitmap.computeByteSize()) {
     return false;
+  }
 
   for (size_t t = 0; t < rgba_area; ++t) {
     // `rgba_data` is RGBA, pixels is ARGB.
@@ -189,8 +191,9 @@
   AppWindowRegistry::AppWindowList windows =
       AppWindowRegistry::Get(profile)->GetAppWindowsForApp(extension_id);
   for (AppWindow* window : windows) {
-    if (window->IsFullscreen() && window->GetBaseWindow()->IsActive())
+    if (window->IsFullscreen() && window->GetBaseWindow()->IsActive()) {
       return true;
+    }
   }
 #endif  // BUILDFLAG(ENABLE_PLATFORM_APPS)
   return false;
@@ -264,15 +267,17 @@
     optional_fields.small_image_needs_additional_masking = true;
   }
 
-  if (options->priority)
+  if (options->priority) {
     optional_fields.priority = *options->priority;
+  }
 
   if (options->event_time)
     optional_fields.timestamp =
         base::Time::FromMillisecondsSinceUnixEpoch(*options->event_time);
 
-  if (options->silent)
+  if (options->silent) {
     optional_fields.silent = *options->silent;
+  }
 
   if (options->buttons) {
     // Currently we allow up to 2 buttons.
@@ -397,10 +402,12 @@
   if (options->type != api::notifications::TemplateType::kNone) {
     notification->set_type(MapApiTemplateTypeToType(options->type));
   }
-  if (options->title)
+  if (options->title) {
     notification->set_title(base::UTF8ToUTF16(*options->title));
-  if (options->message)
+  }
+  if (options->message) {
     notification->set_message(base::UTF8ToUTF16(*options->message));
+  }
 
   if (options->icon_bitmap) {
     gfx::Image icon;
@@ -425,15 +432,17 @@
     notification->set_small_image_needs_additional_masking(true);
   }
 
-  if (options->priority)
+  if (options->priority) {
     notification->set_priority(*options->priority);
+  }
 
   if (options->event_time)
     notification->set_timestamp(
         base::Time::FromMillisecondsSinceUnixEpoch(*options->event_time));
 
-  if (options->silent)
+  if (options->silent) {
     notification->set_silent(*options->silent);
+  }
 
   if (options->buttons) {
     // Currently we allow up to 2 buttons.
@@ -591,8 +600,9 @@
     // Uuid::GenerateRandomV4().AsLowercaseString returns the empty string,
     // simply generate a random string.
     notification_id = base::Uuid::GenerateRandomV4().AsLowercaseString();
-    if (notification_id.empty())
+    if (notification_id.empty()) {
       notification_id = base::RandBytesAsString(16);
+    }
   }
 
   // TODO(dewittj): Add more human-readable error strings if this fails.
diff --git a/chrome/browser/extensions/api/notifications/notifications_apitest.cc b/chrome/browser/extensions/api/notifications/notifications_apitest.cc
index 67cd5dbf..8181600 100644
--- a/chrome/browser/extensions/api/notifications/notifications_apitest.cc
+++ b/chrome/browser/extensions/api/notifications/notifications_apitest.cc
@@ -130,8 +130,9 @@
         AppWindowRegistry::Get(profile())->GetAppWindowsForApp(app_id);
 
     AppWindowRegistry::const_iterator iter = app_windows.begin();
-    if (iter != app_windows.end())
+    if (iter != app_windows.end()) {
       return *iter;
+    }
 
     return nullptr;
   }
@@ -169,8 +170,9 @@
 
     std::set<std::string> notifications =
         GetDisplayHelper()->GetNotificationIdsForExtension(extension->url());
-    if (notifications.size() != 1)
+    if (notifications.size() != 1) {
       return nullptr;
+    }
 
     return GetDisplayHelper()->GetByNotificationId(*notifications.begin());
   }
diff --git a/chrome/browser/extensions/api/offscreen/audio_lifetime_enforcer_browsertest.cc b/chrome/browser/extensions/api/offscreen/audio_lifetime_enforcer_browsertest.cc
index adc939fd..09097d8 100644
--- a/chrome/browser/extensions/api/offscreen/audio_lifetime_enforcer_browsertest.cc
+++ b/chrome/browser/extensions/api/offscreen/audio_lifetime_enforcer_browsertest.cc
@@ -37,8 +37,9 @@
   void WaitForAudible() {
     DCHECK(!expected_state_);
 
-    if (web_contents()->IsCurrentlyAudible())
+    if (web_contents()->IsCurrentlyAudible()) {
       return;
+    }
 
     expected_state_ = true;
     run_loop_.Run();
@@ -47,8 +48,9 @@
   void WaitForInaudible() {
     DCHECK(!expected_state_);
 
-    if (!web_contents()->IsCurrentlyAudible())
+    if (!web_contents()->IsCurrentlyAudible()) {
       return;
+    }
 
     expected_state_ = false;
     run_loop_.Run();
diff --git a/chrome/browser/extensions/api/offscreen/offscreen_apitest.cc b/chrome/browser/extensions/api/offscreen/offscreen_apitest.cc
index 7dab0f2d..bfd1d9c 100644
--- a/chrome/browser/extensions/api/offscreen/offscreen_apitest.cc
+++ b/chrome/browser/extensions/api/offscreen/offscreen_apitest.cc
@@ -493,12 +493,14 @@
          }
 
          chrome.runtime.onMessage.addListener((msg) => {
-           if (msg == 'play')
+           if (msg == 'play') {
              playAudio();
+           }
            else if (msg == 'stop')
              stopAudio();
-           else
+           else {
              console.error('Unexpected message: ' + msg);
+           }
          }))";
   TestExtensionDir test_dir;
   test_dir.WriteManifest(kManifest);
diff --git a/chrome/browser/extensions/api/omnibox/omnibox_api.cc b/chrome/browser/extensions/api/omnibox/omnibox_api.cc
index 9c11213e..158b9a7 100644
--- a/chrome/browser/extensions/api/omnibox/omnibox_api.cc
+++ b/chrome/browser/extensions/api/omnibox/omnibox_api.cc
@@ -81,8 +81,9 @@
     const ExtensionId& extension_id,
     const omnibox::DefaultSuggestResult& suggestion) {
   ExtensionPrefs* prefs = ExtensionPrefs::Get(profile);
-  if (!prefs)
+  if (!prefs) {
     return false;
+  }
 
   base::DictValue dict = suggestion.ToValue();
   // Add the content field so that the dictionary can be used to populate an
@@ -163,12 +164,13 @@
 
   base::ListValue args;
   args.Append(input);
-  if (disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB)
+  if (disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB) {
     args.Append(kForegroundTabDisposition);
-  else if (disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB)
+  } else if (disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) {
     args.Append(kBackgroundTabDisposition);
-  else
+  } else {
     args.Append(kCurrentTabDisposition);
+  }
 
   auto event = std::make_unique<Event>(events::OMNIBOX_ON_INPUT_ENTERED,
                                        omnibox::OnInputEntered::kEventName,
@@ -543,8 +545,9 @@
           return match_classifications;
       }
 
-      for (size_t j = offset; j < offset + length && j < styles.size(); ++j)
+      for (size_t j = offset; j < offset + length && j < styles.size(); ++j) {
         styles[j] |= type_class;
+      }
     }
 
     for (size_t i = 0; i < styles.size(); ++i) {
@@ -569,8 +572,9 @@
 
   std::optional<omnibox::SuggestResult> suggestion(
       GetOmniboxDefaultSuggestion(profile, keyword->GetExtensionId()));
-  if (!suggestion || suggestion->description.empty())
+  if (!suggestion || suggestion->description.empty()) {
     return;  // fall back to the universal default
+  }
 
   const std::u16string kPlaceholderText(u"%s");
   const std::u16string kReplacementText(u"<input>");
@@ -594,8 +598,9 @@
     description.replace(placeholder, kPlaceholderText.length(), replacement);
 
     for (auto& description_style : description_styles) {
-      if (description_style.offset > placeholder)
+      if (description_style.offset > placeholder) {
         description_style.offset += replacement.length() - 2;
+      }
     }
   }
 
diff --git a/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc b/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc
index 3801012a..f7b1754 100644
--- a/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc
+++ b/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc
@@ -98,8 +98,9 @@
 void VerifyMatchComponents(const ExpectedMatchComponents& expected,
                            const AutocompleteMatch& match) {
   std::u16string expected_string;
-  for (const auto& component : expected)
+  for (const auto& component : expected) {
     expected_string += component.text;
+  }
 
   EXPECT_EQ(expected_string, match.contents);
 
diff --git a/chrome/browser/extensions/api/omnibox/suggestion_parser.cc b/chrome/browser/extensions/api/omnibox/suggestion_parser.cc
index 871c4eb..cb82ce0 100644
--- a/chrome/browser/extensions/api/omnibox/suggestion_parser.cc
+++ b/chrome/browser/extensions/api/omnibox/suggestion_parser.cc
@@ -34,8 +34,9 @@
 // Recursively walks an XML node, generating `result` as it goes along.
 void WalkNode(const base::Value& node, DescriptionAndStyles* result) {
   const base::ListValue* children = data_decoder::GetXmlElementChildren(node);
-  if (!children)
+  if (!children) {
     return;
+  }
 
   for (const base::Value& child : *children) {
     // Append text nodes to our description.
@@ -105,13 +106,15 @@
     return false;
   }
 
-  if (CheckedGetElementTag(root_node) != "fragment")
+  if (CheckedGetElementTag(root_node) != "fragment") {
     return false;
+  }
 
   const base::ListValue* children =
       data_decoder::GetXmlElementChildren(root_node);
-  if (!children)
+  if (!children) {
     return false;
+  }
 
   entries_out->reserve(children->size());
   for (const base::Value& child : *children) {
@@ -119,8 +122,9 @@
             child, data_decoder::mojom::XmlParser::kElementType)) {
       return false;
     }
-    if (CheckedGetElementTag(child) != "internal-suggestion")
+    if (CheckedGetElementTag(child) != "internal-suggestion") {
       return false;
+    }
     entries_out->push_back(&child);
   }
 
diff --git a/chrome/browser/extensions/api/page_capture/page_capture_api.cc b/chrome/browser/extensions/api/page_capture/page_capture_api.cc
index 148c6145..1ec9e560 100644
--- a/chrome/browser/extensions/api/page_capture/page_capture_api.cc
+++ b/chrome/browser/extensions/api/page_capture/page_capture_api.cc
@@ -168,8 +168,9 @@
   }
 
   // Let the delegate know the reference has been created.
-  if (test_delegate_)
+  if (test_delegate_) {
     test_delegate_->OnTemporaryFileCreated(mhtml_file_);
+  }
 
   content::GetUIThreadTaskRunner({})->PostTask(
       FROM_HERE,
diff --git a/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc b/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc
index 62d6de3..5a896b7 100644
--- a/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc
+++ b/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc
@@ -39,16 +39,18 @@
   }
 
   void WaitForFinalRelease() {
-    if (temp_file_count_ > 0)
+    if (temp_file_count_ > 0) {
       run_loop_.Run();
+    }
   }
 
   int temp_file_count() const { return temp_file_count_; }
 
  private:
   void OnReleaseCallback(const base::FilePath& path) {
-    if (--temp_file_count_ == 0)
+    if (--temp_file_count_ == 0) {
       release_closure_.Run();
+    }
   }
 
   base::RunLoop run_loop_;
@@ -81,8 +83,9 @@
   void WaitForFileCleanup(PageCaptureSaveAsMHTMLDelegate* delegate) {
     // Garbage collection in SW-based extensions doesn't clean up the temp
     // file.
-    if (GetParam() != ContextType::kServiceWorker)
+    if (GetParam() != ContextType::kServiceWorker) {
       delegate->WaitForFinalRelease();
+    }
   }
 };
 
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc b/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
index 6c5a9842..97bc0cf 100644
--- a/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
+++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
@@ -177,8 +177,9 @@
 
 std::string FormatElapsedTime(base::Time time) {
   const base::TimeDelta elapsed_time = base::Time::Now() - time;
-  if (elapsed_time < base::Minutes(1))
+  if (elapsed_time < base::Minutes(1)) {
     return l10n_util::GetStringUTF8(IDS_PASSWORD_MANAGER_UI_JUST_NOW);
+  }
 
   return base::UTF16ToUTF8(TimeFormat::SimpleWithMonthAndYear(
       TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_LONG, elapsed_time, true));
@@ -297,8 +298,9 @@
     const api::passwords_private::PasswordUiEntry& credential) {
   // Try to obtain the original CredentialUIEntry. Return false if fails.
   const CredentialUIEntry* entry = id_generator_->TryGetKey(credential.id);
-  if (!entry)
+  if (!entry) {
     return false;
+  }
 
   return insecure_credentials_manager_.MuteCredential(*entry);
 }
@@ -307,8 +309,9 @@
     const api::passwords_private::PasswordUiEntry& credential) {
   // Try to obtain the original CredentialUIEntry. Return false if fails.
   const CredentialUIEntry* entry = id_generator_->TryGetKey(credential.id);
-  if (!entry)
+  if (!entry) {
     return false;
+  }
 
   return insecure_credentials_manager_.UnmuteCredential(*entry);
 }
@@ -350,8 +353,9 @@
       base::BindOnce(&PasswordCheckDelegate::NotifyPasswordCheckStatusChanged,
                      weak_ptr_factory_.GetWeakPtr()));
   auto progress = base::MakeRefCounted<PasswordCheckProgress>();
-  for (const auto& password : saved_passwords_presenter_->GetSavedPasswords())
+  for (const auto& password : saved_passwords_presenter_->GetSavedPasswords()) {
     progress->IncrementCounts(password);
+  }
 
   password_check_progress_ = progress->GetWeakPtr();
   PasswordCheckData data(
@@ -430,8 +434,9 @@
   // that the delegate is initialized, and start check callbacks can be invoked,
   // if any.
   if (!std::exchange(is_initialized_, true)) {
-    for (auto&& callback : std::exchange(start_check_callbacks_, {}))
+    for (auto&& callback : std::exchange(start_check_callbacks_, {})) {
       StartPasswordCheck(password_check_initiator_, std::move(callback));
+    }
   }
 
   // A change in the saved passwords might result in leaving or entering the
@@ -474,8 +479,9 @@
   }
 
   // Update the progress in case there is one.
-  if (password_check_progress_)
+  if (password_check_progress_) {
     password_check_progress_->OnProcessed(credential);
+  }
 
   // While the check is still running trigger an update of the check status,
   // considering that the progress has changed.
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc
index cda6fbbe..cef2cb7 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc
@@ -37,9 +37,10 @@
 }
 
 void PasswordsPrivateEventRouter::SendSavedPasswordListToListeners() {
-  if (!cached_saved_password_parameters_.has_value())
+  if (!cached_saved_password_parameters_.has_value()) {
     // If there is nothing to send, return early.
     return;
+  }
 
   auto extension_event = std::make_unique<Event>(
       events::PASSWORDS_PRIVATE_ON_SAVED_PASSWORDS_LIST_CHANGED,
@@ -57,9 +58,10 @@
 }
 
 void PasswordsPrivateEventRouter::SendPasswordExceptionListToListeners() {
-  if (!cached_password_exception_parameters_.has_value())
+  if (!cached_password_exception_parameters_.has_value()) {
     // If there is nothing to send, return early.
     return;
+  }
 
   auto extension_event = std::make_unique<Event>(
       events::PASSWORDS_PRIVATE_ON_PASSWORD_EXCEPTIONS_LIST_CHANGED,
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_utils_chromeos.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_utils_chromeos.cc
index e255482f..e3558f6d 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_utils_chromeos.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_utils_chromeos.cc
@@ -21,16 +21,18 @@
       !ash::password_visibility::AccountHasUserFacingPassword(
           g_browser_process->local_state(),
           ash::ProfileHelper::Get()->GetUserByProfile(profile)->GetAccountId());
-  if (user_cannot_manually_enter_password)
+  if (user_cannot_manually_enter_password) {
     return true;
+  }
   // TODO (b/238606050): This code branch does not seem to be used now.
   //  Clean up the code, or add token as a parameter to this method.
   ash::quick_unlock::QuickUnlockStorage* quick_unlock_storage =
       ash::quick_unlock::QuickUnlockFactory::GetForProfile(profile);
   const ash::quick_unlock::AuthToken* auth_token =
       quick_unlock_storage->GetAuthToken();
-  if (!auth_token || !auth_token->GetAge().has_value())
+  if (!auth_token || !auth_token->GetAge().has_value()) {
     return false;
+  }
 
   return auth_token->GetAge() <= auth_token_lifetime;
 }
diff --git a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc
index 881431d..048f67fd 100644
--- a/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc
+++ b/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc
@@ -149,8 +149,9 @@
 }
 
 void TestPasswordsPrivateDelegate::RemovePasswordException(int id) {
-  if (current_exceptions_.empty())
+  if (current_exceptions_.empty()) {
     return;
+  }
 
   // Since this is just mock data, remove the first element regardless of the
   // data contained.
@@ -424,15 +425,17 @@
 void TestPasswordsPrivateDelegate::SendSavedPasswordsList() {
   PasswordsPrivateEventRouter* router =
       PasswordsPrivateEventRouterFactory::GetForProfile(profile_);
-  if (router)
+  if (router) {
     router->OnSavedPasswordsListChanged(current_entries_);
+  }
 }
 
 void TestPasswordsPrivateDelegate::SendPasswordExceptionsList() {
   PasswordsPrivateEventRouter* router =
       PasswordsPrivateEventRouterFactory::GetForProfile(profile_);
-  if (router)
+  if (router) {
     router->OnPasswordExceptionsListChanged(current_exceptions_);
+  }
 }
 
 bool TestPasswordsPrivateDelegate::IsCredentialPresentInInsecureCredentialsList(
diff --git a/chrome/browser/extensions/api/permissions/permissions_api.cc b/chrome/browser/extensions/api/permissions/permissions_api.cc
index 3abb793..0efbde5 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_api.cc
@@ -158,8 +158,9 @@
               ->AllowFileAccess(extension()->id()),
           &error);
 
-  if (!unpack_result)
+  if (!unpack_result) {
     return RespondNow(Error(std::move(error)));
+  }
 
   const PermissionSet& active_permissions =
       extension()->permissions_data()->active_permissions();
@@ -217,8 +218,9 @@
               ->AllowFileAccess(extension_->id()),
           &error);
 
-  if (!unpack_result)
+  if (!unpack_result) {
     return RespondNow(Error(std::move(error)));
+  }
 
   // We can't remove any permissions that weren't specified in the manifest.
   if (!unpack_result->unlisted_apis.empty() ||
@@ -337,8 +339,9 @@
               ->AllowFileAccess(extension_->id()),
           &error);
 
-  if (!unpack_result)
+  if (!unpack_result) {
     return RespondNow(Error(std::move(error)));
+  }
 
   // Don't allow the extension to request any permissions that weren't specified
   // in the manifest.
@@ -511,8 +514,9 @@
   }
 
   // Grant{Runtime|Optional}Permissions calls above can finish synchronously.
-  if (!did_respond())
+  if (!did_respond()) {
     RespondIfRequestsFinished();
+  }
 }
 
 void PermissionsRequestFunction::OnRuntimePermissionsGranted() {
@@ -526,8 +530,9 @@
 }
 
 void PermissionsRequestFunction::RespondIfRequestsFinished() {
-  if (requesting_withheld_permissions_ || requesting_optional_permissions_)
+  if (requesting_withheld_permissions_ || requesting_optional_permissions_) {
     return;
+  }
 
   Respond(ArgumentList(api::permissions::Request::Results::Create(true)));
 }
diff --git a/chrome/browser/extensions/api/permissions/permissions_api_unittest.cc b/chrome/browser/extensions/api/permissions/permissions_api_unittest.cc
index 5db4d2d..85cf417a50 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api_unittest.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_api_unittest.cc
@@ -62,8 +62,9 @@
     const std::string& name,
     bool allow_file_access) {
   int creation_flags = Extension::NO_FLAGS;
-  if (allow_file_access)
+  if (allow_file_access) {
     creation_flags |= Extension::ALLOW_FILE_ACCESS;
+  }
   return ExtensionBuilder()
       .SetLocation(mojom::ManifestLocation::kInternal)
       .SetManifest(base::DictValue()
diff --git a/chrome/browser/extensions/api/preference/preference_api.cc b/chrome/browser/extensions/api/preference/preference_api.cc
index 994c1f9..fe6ca1b3 100644
--- a/chrome/browser/extensions/api/preference/preference_api.cc
+++ b/chrome/browser/extensions/api/preference/preference_api.cc
@@ -85,8 +85,9 @@
   if (profile->HasPrimaryOTRProfile())
     OnOffTheRecordProfileCreated(
         profile->GetPrimaryOTRProfile(/*create_if_needed=*/true));
-  else
+  else {
     ObserveOffTheRecordPrefs(profile->GetReadOnlyOffTheRecordPrefs());
+  }
 }
 
 PreferenceEventRouter::~PreferenceEventRouter() = default;
@@ -192,8 +193,9 @@
 
 void PreferenceAPI::Shutdown() {
   EventRouter::Get(profile_)->UnregisterObserver(this);
-  if (!ExtensionPrefs::Get(profile_)->extensions_disabled())
+  if (!ExtensionPrefs::Get(profile_)->extensions_disabled()) {
     ClearIncognitoSessionOnlyContentSettings();
+  }
   content_settings_store()->RemoveObserver(this);
 }
 
@@ -295,8 +297,9 @@
   EXTENSION_FUNCTION_VALIDATE(
       PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
       pref_key, &browser_pref, &read_permission, &write_permission));
-  if (!extension()->permissions_data()->HasAPIPermission(read_permission))
+  if (!extension()->permissions_data()->HasAPIPermission(read_permission)) {
     return RespondNow(Error(kPermissionErrorMessage, pref_key));
+  }
 
   Profile* profile = Profile::FromBrowserContext(browser_context());
 
@@ -396,8 +399,9 @@
   EXTENSION_FUNCTION_VALIDATE(
       PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
       pref_key, &browser_pref, &read_permission, &write_permission));
-  if (!extension()->permissions_data()->HasAPIPermission(write_permission))
+  if (!extension()->permissions_data()->HasAPIPermission(write_permission)) {
     return RespondNow(Error(kPermissionErrorMessage, pref_key));
+  }
 
   // As 3PCs are globally blocked in incognito re-allowing them is not
   // supported, so error out.
@@ -498,8 +502,9 @@
   EXTENSION_FUNCTION_VALIDATE(
       PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
       pref_key, &browser_pref, &read_permission, &write_permission));
-  if (!extension()->permissions_data()->HasAPIPermission(write_permission))
+  if (!extension()->permissions_data()->HasAPIPermission(write_permission)) {
     return RespondNow(Error(kPermissionErrorMessage, pref_key));
+  }
 
   auto* prefs_helper = ExtensionPrefsHelper::Get(browser_context());
 
diff --git a/chrome/browser/extensions/api/printer_provider/printer_provider_apitest.cc b/chrome/browser/extensions/api/printer_provider/printer_provider_apitest.cc
index 2ebad5d..dd5a498 100644
--- a/chrome/browser/extensions/api/printer_provider/printer_provider_apitest.cc
+++ b/chrome/browser/extensions/api/printer_provider/printer_provider_apitest.cc
@@ -169,8 +169,9 @@
     ExtensionId extension_id;
     InitializePrinterProviderTestExtension("printer_provider/request_print",
                                            test_param, &extension_id);
-    if (extension_id.empty())
+    if (extension_id.empty()) {
       return;
+    }
 
     base::RunLoop run_loop;
     bool success;
@@ -188,8 +189,9 @@
         break;
     }
 
-    if (data_type != PRINT_REQUEST_DATA_TYPE_NOT_SET)
+    if (data_type != PRINT_REQUEST_DATA_TYPE_NOT_SET) {
       ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
+    }
 
     run_loop.Run();
     EXPECT_EQ(expected_result, status);
@@ -207,8 +209,9 @@
     ExtensionId extension_id;
     InitializePrinterProviderTestExtension(
         "printer_provider/request_capability", test_param, &extension_id);
-    if (extension_id.empty())
+    if (extension_id.empty()) {
       return;
+    }
 
     base::test::TestFuture<base::DictValue> capability_future;
     StartCapabilityRequest(extension_id, capability_future.GetCallback());
@@ -225,8 +228,9 @@
 
     scoped_refptr<const Extension> extension =
         extension_registry->enabled_extensions().GetByID(extension_id);
-    if (!extension)
+    if (!extension) {
       return false;
+    }
 
     extension_registry->RemoveEnabled(extension_id);
     extension_registry->TriggerOnUnloaded(extension.get(),
diff --git a/chrome/browser/extensions/api/printing/fake_print_job_controller.cc b/chrome/browser/extensions/api/printing/fake_print_job_controller.cc
index 28c2094..89e202f 100644
--- a/chrome/browser/extensions/api/printing/fake_print_job_controller.cc
+++ b/chrome/browser/extensions/api/printing/fake_print_job_controller.cc
@@ -61,10 +61,11 @@
       printing::PrintSettings::NewCookie());
   int observer_count = 0;
   for (auto& observer : job->GetObserversForTesting()) {
-    if (fail_)
+    if (fail_) {
       observer.OnFailed();
-    else
+    } else {
       observer.OnDocDone(job_id_, document.get());
+    }
     observer_count++;
   }
   EXPECT_EQ(1, observer_count);
diff --git a/chrome/browser/extensions/api/printing/print_job_submitter.cc b/chrome/browser/extensions/api/printing/print_job_submitter.cc
index 64f24f2db..69fae97fa 100644
--- a/chrome/browser/extensions/api/printing/print_job_submitter.cc
+++ b/chrome/browser/extensions/api/printing/print_job_submitter.cc
@@ -71,8 +71,9 @@
 // Returns true if print job request dialog should be shown.
 bool IsUserConfirmationRequired(content::BrowserContext* browser_context,
                                 const std::string& extension_id) {
-  if (g_skip_confirmation_dialog_for_testing)
+  if (g_skip_confirmation_dialog_for_testing) {
     return false;
+  }
   const base::ListValue& list =
       Profile::FromBrowserContext(browser_context)
           ->GetPrefs()
@@ -100,8 +101,9 @@
       local_printer_(local_printer),
       callback_(std::move(callback)) {
   DCHECK(extension);
-  if (native_window)
+  if (native_window) {
     native_window_tracker_ = ui::NativeWindowTracker::Create(native_window);
+  }
 }
 
 PrintJobSubmitter::~PrintJobSubmitter() = default;
@@ -136,8 +138,9 @@
 
 bool PrintJobSubmitter::CheckPrintTicket() {
   settings_ = ParsePrintTicket(request_.job.ticket.ToValue());
-  if (!settings_)
+  if (!settings_) {
     return false;
+  }
   settings_->set_title(base::UTF8ToUTF16(request_.job.title));
   settings_->set_device_name(base::UTF8ToUTF16(request_.job.printer_id));
   return true;
diff --git a/chrome/browser/extensions/api/printing/printing_api.cc b/chrome/browser/extensions/api/printing/printing_api.cc
index 346ba52..90ea5492 100644
--- a/chrome/browser/extensions/api/printing/printing_api.cc
+++ b/chrome/browser/extensions/api/printing/printing_api.cc
@@ -64,8 +64,9 @@
       PrintingAPIHandler::Get(browser_context())
           ->CancelJob(extension_id(), params->job_id);
 
-  if (error.has_value())
+  if (error.has_value()) {
     return RespondNow(Error(error.value()));
+  }
   return RespondNow(NoArguments());
 }
 
diff --git a/chrome/browser/extensions/api/printing/printing_api_handler.cc b/chrome/browser/extensions/api/printing/printing_api_handler.cc
index 84287cbc..c5b6223 100644
--- a/chrome/browser/extensions/api/printing/printing_api_handler.cc
+++ b/chrome/browser/extensions/api/printing/printing_api_handler.cc
@@ -174,8 +174,9 @@
   if (!result.has_value()) {
     std::optional<std::string> error = std::move(result).error();
     std::optional<api::printing::SubmitJobStatus> status;
-    if (!error)
+    if (!error) {
       status = api::printing::SubmitJobStatus::kUserRejected;
+    }
     base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback), status, std::nullopt,
                                   std::move(error)));
diff --git a/chrome/browser/extensions/api/printing/printing_api_utils.cc b/chrome/browser/extensions/api/printing/printing_api_utils.cc
index 3f542d9..523bbef 100644
--- a/chrome/browser/extensions/api/printing/printing_api_utils.cc
+++ b/chrome/browser/extensions/api/printing/printing_api_utils.cc
@@ -53,8 +53,9 @@
 bool DoesPrinterMatchDefaultPrinterRules(
     const chromeos::Printer& printer,
     const std::optional<DefaultPrinterRules>& rules) {
-  if (!rules.has_value())
+  if (!rules.has_value()) {
     return false;
+  }
   return (rules->kind.empty() || rules->kind == kLocal) &&
          (rules->id_pattern.empty() ||
           RE2::FullMatch(printer.id(), rules->id_pattern)) &&
@@ -100,8 +101,9 @@
 
 std::optional<DefaultPrinterRules> GetDefaultPrinterRules(
     const std::string& default_destination_selection_rules) {
-  if (default_destination_selection_rules.empty())
+  if (default_destination_selection_rules.empty()) {
     return std::nullopt;
+  }
 
   std::optional<base::Value> default_destination_selection_rules_value =
       base::JSONReader::Read(default_destination_selection_rules,
@@ -351,11 +353,13 @@
 bool CheckSettingsAndCapabilitiesCompatibility(
     const printing::PrintSettings& settings,
     const printing::PrinterSemanticCapsAndDefaults& capabilities) {
-  if (settings.collate() && !capabilities.collate_capable)
+  if (settings.collate() && !capabilities.collate_capable) {
     return false;
+  }
 
-  if (settings.copies() > capabilities.copies_max)
+  if (settings.copies() > capabilities.copies_max) {
     return false;
+  }
 
   if (!std::ranges::contains(capabilities.duplex_modes,
                              settings.duplex_mode())) {
diff --git a/chrome/browser/extensions/api/processes/processes_api.cc b/chrome/browser/extensions/api/processes/processes_api.cc
index d997b9c..863b1eae 100644
--- a/chrome/browser/extensions/api/processes/processes_api.cc
+++ b/chrome/browser/extensions/api/processes/processes_api.cc
@@ -128,19 +128,22 @@
     api::processes::TaskInfo task_info;
     task_info.title = base::UTF16ToUTF8(task_manager->GetTitle(task_id));
     const SessionID tab_id = task_manager->GetTabId(task_id);
-    if (tab_id.is_valid())
+    if (tab_id.is_valid()) {
       task_info.tab_id = tab_id.id();
+    }
 
     out_process->tasks.push_back(std::move(task_info));
   }
 
   // If we don't need to include the optional properties, just return now.
-  if (!include_optional)
+  if (!include_optional) {
     return;
+  }
 
   const double cpu_usage = task_manager->GetPlatformIndependentCPUUsage(id);
-  if (!std::isnan(cpu_usage))
+  if (!std::isnan(cpu_usage)) {
     out_process->cpu = cpu_usage;
+  }
 
   const std::optional<base::ByteSize> network_usage =
       task_manager->GetProcessTotalNetworkUsage(id);
@@ -203,12 +206,14 @@
 }
 
 void ProcessesEventRouter::OnTaskAdded(task_manager::TaskId id) {
-  if (!HasEventListeners(api::processes::OnCreated::kEventName))
+  if (!HasEventListeners(api::processes::OnCreated::kEventName)) {
     return;
+  }
 
   int child_process_host_id = 0;
-  if (!ShouldReportOnCreatedOrOnExited(id, &child_process_host_id))
+  if (!ShouldReportOnCreatedOrOnExited(id, &child_process_host_id)) {
     return;
+  }
 
   api::processes::Process process;
   FillProcessData(id,
@@ -221,12 +226,14 @@
 }
 
 void ProcessesEventRouter::OnTaskToBeRemoved(task_manager::TaskId id) {
-  if (!HasEventListeners(api::processes::OnExited::kEventName))
+  if (!HasEventListeners(api::processes::OnExited::kEventName)) {
     return;
+  }
 
   int child_process_host_id = 0;
-  if (!ShouldReportOnCreatedOrOnExited(id, &child_process_host_id))
+  if (!ShouldReportOnCreatedOrOnExited(id, &child_process_host_id)) {
     return;
+  }
 
   int exit_code = 0;
   base::TerminationStatus status = base::TERMINATION_STATUS_STILL_RUNNING;
@@ -246,8 +253,9 @@
   const bool has_on_updated_with_memory_listeners =
       HasEventListeners(api::processes::OnUpdatedWithMemory::kEventName);
 
-  if (!has_on_updated_listeners && !has_on_updated_with_memory_listeners)
+  if (!has_on_updated_listeners && !has_on_updated_with_memory_listeners) {
     return;
+  }
 
   // Get the data of tasks sharing the same process only once.
   std::set<base::ProcessId> seen_processes;
@@ -257,15 +265,17 @@
     // run.
     const base::ProcessId proc_id =
         observed_task_manager()->GetProcessId(task_id);
-    if (seen_processes.count(proc_id))
+    if (seen_processes.count(proc_id)) {
       continue;
+    }
 
     const int child_process_host_id =
         observed_task_manager()->GetChildProcessUniqueId(task_id);
     // Ignore tasks that don't have a valid child process host ID like ARC
     // processes. We report the browser process info here though.
-    if (child_process_host_id == content::ChildProcessHost::kInvalidUniqueID)
+    if (child_process_host_id == content::ChildProcessHost::kInvalidUniqueID) {
       continue;
+    }
 
     seen_processes.insert(proc_id);
     api::processes::Process process;
@@ -312,8 +322,9 @@
 }
 
 void ProcessesEventRouter::OnTaskUnresponsive(task_manager::TaskId id) {
-  if (!HasEventListeners(api::processes::OnUnresponsive::kEventName))
+  if (!HasEventListeners(api::processes::OnUnresponsive::kEventName)) {
     return;
+  }
 
   api::processes::Process process;
   FillProcessData(id,
@@ -346,8 +357,9 @@
     task_manager::TaskId id,
     int* out_child_process_host_id) const {
   // Is it the first task to be created or the last one to be removed?
-  if (observed_task_manager()->GetNumberOfTasksOnSameProcess(id) != 1)
+  if (observed_task_manager()->GetNumberOfTasksOnSameProcess(id) != 1) {
     return false;
+  }
 
   // Ignore tasks that don't have a valid child process host ID like ARC
   // processes, as well as the browser process (neither onCreated() nor
@@ -367,8 +379,9 @@
   int64_t refresh_types = task_manager::REFRESH_TYPE_NONE;
 
   const int64_t on_updated_types = GetRefreshTypesForProcessOptionalData();
-  if (HasEventListeners(api::processes::OnUpdated::kEventName))
+  if (HasEventListeners(api::processes::OnUpdated::kEventName)) {
     refresh_types |= on_updated_types;
+  }
 
   if (HasEventListeners(api::processes::OnUpdatedWithMemory::kEventName)) {
     refresh_types |=
@@ -509,8 +522,9 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   auto* host = content::BrowserChildProcessHost::FromID(child_process_host_id);
-  if (host)
+  if (host) {
     return host->GetData().GetProcess().Handle();
+  }
 
   return base::kNullProcessHandle;
 }
@@ -560,14 +574,16 @@
   std::optional<api::processes::GetProcessInfo::Params> params =
       api::processes::GetProcessInfo::Params::Create(args());
   EXTENSION_FUNCTION_VALIDATE(params);
-  if (params->process_ids.as_integer)
+  if (params->process_ids.as_integer) {
     process_host_ids_.push_back(*params->process_ids.as_integer);
-  else
+  } else {
     process_host_ids_.swap(*params->process_ids.as_integers);
+  }
 
   include_memory_ = params->include_memory;
-  if (include_memory_)
+  if (include_memory_) {
     AddRefreshType(task_manager::REFRESH_TYPE_MEMORY_FOOTPRINT);
+  }
 
   // Keep this object alive until the first of either OnTasksRefreshed() or
   // OnTasksRefreshedWithBackgroundCalculations() is received depending on
@@ -585,8 +601,9 @@
     const task_manager::TaskIdList& task_ids) {
   // Memory is background calculated and will be ready when
   // OnTasksRefreshedWithBackgroundCalculations() is invoked.
-  if (include_memory_)
+  if (include_memory_) {
     return;
+  }
 
   GatherDataAndRespond(task_ids);
 }
@@ -594,8 +611,9 @@
 void
 ProcessesGetProcessInfoFunction::OnTasksRefreshedWithBackgroundCalculations(
     const task_manager::TaskIdList& task_ids) {
-  if (!include_memory_)
+  if (!include_memory_) {
     return;
+  }
 
   GatherDataAndRespond(task_ids);
 }
@@ -614,22 +632,25 @@
   for (const auto& task_id : task_ids) {
     const base::ProcessId proc_id =
         observed_task_manager()->GetProcessId(task_id);
-    if (seen_processes.count(proc_id))
+    if (seen_processes.count(proc_id)) {
       continue;
+    }
 
     const int child_process_host_id =
         observed_task_manager()->GetChildProcessUniqueId(task_id);
     // Ignore tasks that don't have a valid child process host ID like ARC
     // processes. We report the browser process info here though.
-    if (child_process_host_id == content::ChildProcessHost::kInvalidUniqueID)
+    if (child_process_host_id == content::ChildProcessHost::kInvalidUniqueID) {
       continue;
+    }
 
     if (specific_processes_requested) {
       // Note: we can't use |!process_host_ids_.empty()| directly in the above
       // condition as we will erase from |process_host_ids_| below.
       auto itr = std::ranges::find(process_host_ids_, child_process_host_id);
-      if (itr == process_host_ids_.end())
+      if (itr == process_host_ids_.end()) {
         continue;
+      }
 
       // If found, we remove it from |process_host_ids|, so that at the end if
       // anything remains in |process_host_ids|, those were invalid arguments
diff --git a/chrome/browser/extensions/api/processes/processes_apitest.cc b/chrome/browser/extensions/api/processes/processes_apitest.cc
index 11f4e3f..4086ae03 100644
--- a/chrome/browser/extensions/api/processes/processes_apitest.cc
+++ b/chrome/browser/extensions/api/processes/processes_apitest.cc
@@ -108,8 +108,9 @@
       task_manager::REFRESH_TYPE_WEBCACHE_STATS,
   };
 
-  for (const auto& type : kOnUpdatedRefreshTypes)
+  for (const auto& type : kOnUpdatedRefreshTypes) {
     EXPECT_TRUE(task_manager->IsResourceRefreshEnabled(type));
+  }
 
   // Unload the extensions and make sure the listeners count is updated.
   UnloadExtension(extension->id());
diff --git a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
index 10e3ce8..38e0617b 100644
--- a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
+++ b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
@@ -57,8 +57,9 @@
     const std::string& pac_script_url_base64_encoded,
     std::string* pac_script) {
   GURL url(pac_script_url_base64_encoded);
-  if (!url.is_valid())
+  if (!url.is_valid()) {
     return false;
+  }
 
   std::string mime_type;
   std::string charset;
@@ -118,8 +119,9 @@
                                 bool* bad_message) {
   const base::DictValue* pac_dict =
       proxy_config.FindDict(proxy_api_constants::kProxyConfigPacScript);
-  if (!pac_dict)
+  if (!pac_dict) {
     return true;
+  }
 
   // TODO(battre): Handle UTF-8 URLs (http://crbug.com/72692).
   std::string pac_url;
@@ -148,8 +150,9 @@
                                  bool* bad_message) {
   const base::DictValue* pac_dict =
       proxy_config.FindDict(proxy_api_constants::kProxyConfigPacScript);
-  if (!pac_dict)
+  if (!pac_dict) {
     return true;
+  }
 
   std::string pac_data;
   const base::Value* pac_val =
@@ -188,8 +191,9 @@
   }
 
   net::ProxyServer::Scheme scheme = net::GetSchemeFromUriScheme(scheme_string);
-  if (scheme == net::ProxyServer::SCHEME_INVALID)
+  if (scheme == net::ProxyServer::SCHEME_INVALID) {
     scheme = default_scheme;
+  }
 
   // TODO(battre): handle UTF-8 in hostnames (http://crbug.com/72692).
   std::u16string host16;
@@ -230,8 +234,9 @@
                                           bool* bad_message) {
   const base::DictValue* proxy_rules =
       proxy_config.FindDict(proxy_api_constants::kProxyConfigRules);
-  if (!proxy_rules)
+  if (!proxy_rules) {
     return true;
+  }
 
   // Local data into which the parameters will be parsed. has_proxy describes
   // whether a setting was found for the scheme; proxy_server holds the
@@ -277,8 +282,9 @@
   for (size_t i = 1; i <= SCHEME_MAX; ++i) {
     if (has_proxy[i]) {
       // http=foopy:4010;ftp=socks5://foopy2:80
-      if (!proxy_pref.empty())
+      if (!proxy_pref.empty()) {
         proxy_pref.append(";");
+      }
       proxy_pref.append(kSchemeNames[i]);
       proxy_pref.append("=");
       proxy_pref.append(net::ProxyServerToProxyUri(proxy_server[i]));
@@ -296,8 +302,9 @@
                  bool* bad_message) {
   std::string result;
   for (const auto& val : list) {
-    if (!result.empty())
+    if (!result.empty()) {
       result.append(joiner);
+    }
 
     // TODO(battre): handle UTF-8 (http://crbug.com/72692).
     const std::string* entry = val.GetIfString();
@@ -323,8 +330,9 @@
                                     bool* bad_message) {
   const base::DictValue* proxy_rules =
       proxy_config.FindDict(proxy_api_constants::kProxyConfigRules);
-  if (!proxy_rules)
+  if (!proxy_rules) {
     return true;
+  }
 
   const base::Value* bypass_list =
       proxy_rules->Find(proxy_api_constants::kProxyConfigBypassList);
@@ -523,8 +531,9 @@
                                      const std::string& delims) {
   base::ListValue out;
   base::StringTokenizer entries(in, delims);
-  while (entries.GetNext())
+  while (entries.GetNext()) {
     out.Append(entries.token_piece());
+  }
   return out;
 }
 
diff --git a/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api.cc b/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api.cc
index b2ed752..e8f3a61 100644
--- a/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api.cc
+++ b/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api.cc
@@ -86,8 +86,9 @@
       base::BindOnce(
           [](ActiveModeCallback result, bool is_set) {
             QuickUnlockModeList modes;
-            if (is_set)
+            if (is_set) {
               modes.push_back(quick_unlock_private::QuickUnlockMode::kPin);
+            }
             std::move(result).Run(modes);
           },
           std::move(result)));
@@ -96,8 +97,9 @@
 // Returns true if |a| and |b| contain the same elements. The elements do not
 // need to be in the same order.
 bool AreModesEqual(const QuickUnlockModeList& a, const QuickUnlockModeList& b) {
-  if (a.size() != b.size())
+  if (a.size() != b.size()) {
     return false;
+  }
 
   // This is a slow comparison algorithm, but the number of entries in |a| and
   // |b| will always be very low (0-3 items) so it doesn't matter.
@@ -142,13 +144,15 @@
       GetSanitizedPolicyPinMinMaxLength(pref_service);
 
   // Check if the PIN is shorter than the minimum specified length.
-  if (pin.size() < static_cast<size_t>(min_length))
+  if (pin.size() < static_cast<size_t>(min_length)) {
     return CredentialProblem::kTooShort;
+  }
 
   // If the maximum specified length is zero, there is no maximum length.
   // Otherwise check if the PIN is longer than the maximum specified length.
-  if (max_length != 0 && pin.size() > static_cast<size_t>(max_length))
+  if (max_length != 0 && pin.size() > static_cast<size_t>(max_length)) {
     return CredentialProblem::kTooLong;
+  }
 
   return CredentialProblem::kNone;
 }
@@ -163,8 +167,9 @@
 bool IsPinDifficultEnough(const std::string& pin) {
   // If the pin length is |kMinLengthForNonWeakPin| or less, there is no need to
   // check for same character and increasing pin.
-  if (pin.size() <= kMinLengthForNonWeakPin)
+  if (pin.size() <= kMinLengthForNonWeakPin) {
     return true;
+  }
 
   // Check if it is on the list of most common PINs.
   if (std::ranges::contains(kMostCommonPins, pin)) {
@@ -185,8 +190,9 @@
   }
 
   // PIN is considered weak if any of these conditions is met.
-  if (is_same || is_increasing || is_decreasing)
+  if (is_same || is_increasing || is_decreasing) {
     return false;
+  }
 
   return true;
 }
@@ -195,8 +201,9 @@
   Profile* profile = Profile::FromBrowserContext(browser_context);
   // When OOBE continues in-session as Furst Run UI, it is still executed
   // under Sign-In profile.
-  if (ash::ProfileHelper::IsSigninProfile(profile))
+  if (ash::ProfileHelper::IsSigninProfile(profile)) {
     return profile_util::GetPrimaryUserProfile();
+  }
 
   return profile;
 }
@@ -424,8 +431,9 @@
   // Check and return the problems.
   std::vector<CredentialProblem>& warnings = result->warnings;
   std::vector<CredentialProblem>& errors = result->errors;
-  if (!IsPinNumeric(credential))
+  if (!IsPinNumeric(credential)) {
     errors.push_back(CredentialProblem::kContainsNondigit);
+  }
 
   CredentialProblem length_problem =
       GetCredentialProblemForPin(credential, pref_service);
@@ -493,11 +501,13 @@
   params_ = SetModes::Params::Create(args());
   EXTENSION_FUNCTION_VALIDATE(params_);
 
-  if (params_->modes.size() != params_->credentials.size())
+  if (params_->modes.size() != params_->credentials.size()) {
     return RespondNow(Error(kModesAndCredentialsLengthMismatch));
+  }
 
-  if (params_->modes.size() > 1)
+  if (params_->modes.size() > 1) {
     return RespondNow(Error(kMultipleModesNotSupported));
+  }
 
   std::optional<std::string> error =
       CheckTokenValidity(browser_context(), params_->token);
@@ -522,15 +532,17 @@
   bool allow_weak =
       pref_service->GetBoolean(ash::prefs::kPinUnlockWeakPinsAllowed);
   for (size_t i = 0; i < params_->modes.size(); ++i) {
-    if (params_->credentials[i].empty())
+    if (params_->credentials[i].empty()) {
       continue;
+    }
 
     if (params_->modes[i] != QuickUnlockMode::kPin) {
       continue;
     }
 
-    if (!IsPinNumeric(params_->credentials[i]))
+    if (!IsPinNumeric(params_->credentials[i])) {
       return RespondNow(Error(kInvalidPIN));
+    }
 
     CredentialProblem problem =
         GetCredentialProblemForPin(params_->credentials[i], pref_service);
@@ -538,8 +550,9 @@
       return RespondNow(Error(kInvalidCredential));
     }
 
-    if (!allow_weak && !IsPinDifficultEnough(params_->credentials[i]))
+    if (!allow_weak && !IsPinDifficultEnough(params_->credentials[i])) {
       return RespondNow(Error(kWeakCredential));
+    }
   }
 
   ComputeActiveModes(
@@ -619,8 +632,9 @@
 
 void QuickUnlockPrivateSetModesFunction::ModeChangeComplete(
     const std::vector<QuickUnlockMode>& updated_modes) {
-  if (!AreModesEqual(initial_modes_, updated_modes))
+  if (!AreModesEqual(initial_modes_, updated_modes)) {
     FireEvent(updated_modes);
+  }
 
   const user_manager::User* const user =
       ash::ProfileHelper::Get()->GetUserByProfile(
diff --git a/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api_unittest.cc b/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api_unittest.cc
index 85c4fca02..2eea65a 100644
--- a/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api_unittest.cc
@@ -436,13 +436,15 @@
     params.Append(token);
 
     base::ListValue serialized_modes;
-    for (QuickUnlockMode mode : modes)
+    for (QuickUnlockMode mode : modes) {
       serialized_modes.Append(quick_unlock_private::ToString(mode));
+    }
     params.Append(base::Value(std::move(serialized_modes)));
 
     base::ListValue serialized_passwords;
-    for (const std::string& password : passwords)
+    for (const std::string& password : passwords) {
       serialized_passwords.Append(password);
+    }
     params.Append(base::Value(std::move(serialized_passwords)));
 
     return params;
diff --git a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_util.cc b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_util.cc
index 5695ef4..f010837 100644
--- a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_util.cc
+++ b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_util.cc
@@ -52,8 +52,9 @@
   if (referrer.ip_addresses_size() > 0) {
     entry.ip_addresses.emplace();
     entry.ip_addresses->reserve(referrer.ip_addresses_size());
-    for (const std::string& ip_address : referrer.ip_addresses())
+    for (const std::string& ip_address : referrer.ip_addresses()) {
       entry.ip_addresses->emplace_back(ip_address);
+    }
   }
   if (referrer.has_referrer_url()) {
     entry.referrer_url = referrer.referrer_url();
@@ -61,8 +62,9 @@
   if (referrer.has_referrer_main_frame_url()) {
     entry.referrer_main_frame_url = referrer.referrer_main_frame_url();
   }
-  if (referrer.has_is_retargeting())
+  if (referrer.has_is_retargeting()) {
     entry.is_retargeting = referrer.is_retargeting();
+  }
   if (referrer.has_navigation_time_msec()) {
     entry.navigation_time_ms = referrer.navigation_time_msec();
   }
diff --git a/chrome/browser/extensions/api/scripting/scripting_api.cc b/chrome/browser/extensions/api/scripting/scripting_api.cc
index a77e04b..eadced3a 100644
--- a/chrome/browser/extensions/api/scripting/scripting_api.cc
+++ b/chrome/browser/extensions/api/scripting/scripting_api.cc
@@ -289,8 +289,9 @@
   }
 
   if (injection_.files) {
-    if (injection_.args)
+    if (injection_.args) {
       return RespondNow(Error("'args' may not be used with file injections."));
+    }
 
     // JS files don't require localization.
     constexpr bool kRequiresLocalization = false;
@@ -318,8 +319,9 @@
     string_args.reserve(injection_.args->size());
     for (const auto& arg : *injection_.args) {
       std::string json;
-      if (!base::JSONWriter::Write(arg, &json))
+      if (!base::JSONWriter::Write(arg, &json)) {
         return RespondNow(Error("Unserializable argument passed."));
+      }
       string_args.push_back(std::move(json));
     }
     args_expression = base::JoinString(string_args, ",");
@@ -332,8 +334,9 @@
   sources.push_back(mojom::JSSource::New(std::move(code_to_execute), GURL()));
 
   std::string error;
-  if (!Execute(std::move(sources), &error))
+  if (!Execute(std::move(sources), &error)) {
     return RespondNow(Error(std::move(error)));
+  }
 
   return RespondLater();
 }
@@ -399,13 +402,15 @@
   // to the extension.
   std::vector<api::scripting::InjectionResult> injection_results;
   for (auto& result : frame_results) {
-    if (!result.error.empty())
+    if (!result.error.empty()) {
       continue;
+    }
     api::scripting::InjectionResult injection_result;
     injection_result.result = std::move(result.value);
     injection_result.frame_id = result.frame_id;
-    if (result.document_id)
+    if (result.document_id) {
       injection_result.document_id = result.document_id.ToString();
+    }
 
     // Put the top frame first; otherwise, any order.
     if (result.frame_id == ExtensionApiFrameIdMap::kTopFrameId) {
@@ -481,8 +486,9 @@
       FileSourcesToCSSSources(*extension(), std::move(file_sources));
 
   std::string error;
-  if (!Execute(std::move(sources), &error))
+  if (!Execute(std::move(sources), &error)) {
     Respond(Error(std::move(error)));
+  }
 }
 
 bool ScriptingInsertCSSFunction::Execute(
@@ -743,10 +749,11 @@
 
 void ScriptingRegisterContentScriptsFunction::OnContentScriptsRegistered(
     const std::optional<std::string>& error) {
-  if (error.has_value())
+  if (error.has_value()) {
     Respond(Error(std::move(*error)));
-  else
+  } else {
     Respond(NoArguments());
+  }
   Release();  // Matches the `AddRef()` in `Run()`.
 }
 
@@ -843,10 +850,11 @@
 
 void ScriptingUnregisterContentScriptsFunction::OnContentScriptsUnregistered(
     const std::optional<std::string>& error) {
-  if (error.has_value())
+  if (error.has_value()) {
     Respond(Error(std::move(*error)));
-  else
+  } else {
     Respond(NoArguments());
+  }
 }
 
 ScriptingUpdateContentScriptsFunction::ScriptingUpdateContentScriptsFunction() =
@@ -1023,10 +1031,11 @@
 
 void ScriptingUpdateContentScriptsFunction::OnContentScriptsUpdated(
     const std::optional<std::string>& error) {
-  if (error.has_value())
+  if (error.has_value()) {
     Respond(Error(std::move(*error)));
-  else
+  } else {
     Respond(NoArguments());
+  }
   Release();  // Matches the `AddRef()` in `Run()`.
 }
 
diff --git a/chrome/browser/extensions/api/scripting/scripting_apitest.cc b/chrome/browser/extensions/api/scripting/scripting_apitest.cc
index a214bf77..447d0a7f 100644
--- a/chrome/browser/extensions/api/scripting/scripting_apitest.cc
+++ b/chrome/browser/extensions/api/scripting/scripting_apitest.cc
@@ -61,8 +61,9 @@
 // Returns the IDs of all divs in a page; used for testing script injections.
 constexpr char kGetDivIds[] =
     R"(let childIds = [];
-       for (const child of document.body.children)
+       for (const child of document.body.children) {
          childIds.push(child.id);
+       }
        JSON.stringify(childIds.sort());)";
 #endif
 
diff --git a/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc b/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc
index 0c98f3542..10f25ce 100644
--- a/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc
+++ b/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc
@@ -83,17 +83,20 @@
     }
   }
 
-  if (!data)
+  if (!data) {
     data = std::make_unique<TemplateURLData>();
+  }
 
   // `prepopulate_id` must be 0 to avoid collisions with prepopulated
   // engines.
   DCHECK_EQ(0, data->prepopulate_id);
 
-  if (search_provider.name)
+  if (search_provider.name) {
     data->SetShortName(base::UTF8ToUTF16(*search_provider.name));
-  if (search_provider.keyword)
+  }
+  if (search_provider.keyword) {
     data->SetKeyword(base::UTF8ToUTF16(*search_provider.keyword));
+  }
   data->SetURL(
       SubstituteInstallParam(search_provider.search_url, install_parameter));
   if (search_provider.suggest_url) {
@@ -104,13 +107,15 @@
     data->image_url =
         SubstituteInstallParam(*search_provider.image_url, install_parameter);
   }
-  if (search_provider.search_url_post_params)
+  if (search_provider.search_url_post_params) {
     data->search_url_post_params = *search_provider.search_url_post_params;
+  }
   if (search_provider.suggest_url_post_params)
     data->suggestions_url_post_params =
         *search_provider.suggest_url_post_params;
-  if (search_provider.image_url_post_params)
+  if (search_provider.image_url_post_params) {
     data->image_url_post_params = *search_provider.image_url_post_params;
+  }
   if (search_provider.favicon_url) {
     data->favicon_url = GURL(SubstituteInstallParam(
         *search_provider.favicon_url, install_parameter));
@@ -155,8 +160,9 @@
   // This is not instantiated in unit tests. Historically, the PreferenceAPI
   // instance provided this functionality, and it was not instantiated during
   // unit tests and some tests relied on that.
-  if (!prefs_helper)
+  if (!prefs_helper) {
     return;
+  }
 
   prefs_helper->SetExtensionControlledPref(
       extension_id, pref_key, ChromeSettingScope::kRegular, std::move(value));
@@ -166,8 +172,9 @@
                                      const std::string& pref_key) const {
   ExtensionPrefsHelper* prefs_helper = ExtensionPrefsHelper::Get(profile_);
   // Not instantiated in unit tests.
-  if (!prefs_helper)
+  if (!prefs_helper) {
     return;
+  }
   prefs_helper->RemoveExtensionControlledPref(extension_id, pref_key,
                                               ChromeSettingScope::kRegular);
 }
diff --git a/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc b/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc
index ccfff11..ddf8fc1 100644
--- a/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc
+++ b/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc
@@ -105,11 +105,13 @@
 
 testing::AssertionResult VerifyTemplateURLServiceLoad(
     TemplateURLService* service) {
-  if (service->loaded())
+  if (service->loaded()) {
     return testing::AssertionSuccess();
+  }
   search_test_utils::WaitForTemplateURLServiceToLoad(service);
-  if (service->loaded())
+  if (service->loaded()) {
     return testing::AssertionSuccess();
+  }
   return testing::AssertionFailure() << "TemplateURLService isn't loaded";
 }
 
diff --git a/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_method_short.cc b/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_method_short.cc
index cdb32d5..dcf273c1 100644
--- a/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_method_short.cc
+++ b/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_method_short.cc
@@ -65,8 +65,9 @@
 
 SetPrefResult GeneratedResolveTimezoneByGeolocationMethodShort::SetPref(
     const base::Value* value) {
-  if (!value->is_int())
+  if (!value->is_int()) {
     return SetPrefResult::PREF_TYPE_MISMATCH;
+  }
 
   // Check if preference is policy or primary-user controlled.
   if (ash::system::TimeZoneResolverManager::
@@ -91,8 +92,9 @@
                           ->GetTimezoneResolverManager()
                           ->GetEffectiveUserTimeZoneResolveMethod(
                               profile_->GetPrefs(), true);
-  if (new_value == current_value)
+  if (new_value == current_value) {
     return SetPrefResult::SUCCESS;
+  }
 
   profile_->GetPrefs()->SetInteger(::prefs::kResolveTimezoneByGeolocationMethod,
                                    static_cast<int>(new_value));
diff --git a/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.cc b/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.cc
index bf6843970..9d11c0c3 100644
--- a/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.cc
+++ b/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.cc
@@ -66,8 +66,9 @@
 
 SetPrefResult GeneratedResolveTimezoneByGeolocationOnOff::SetPref(
     const base::Value* value) {
-  if (!value->is_bool())
+  if (!value->is_bool()) {
     return SetPrefResult::PREF_TYPE_MISMATCH;
+  }
 
   // Check if preference is policy or primary-user controlled, and therefore
   // cannot deactivate automatic timezone.
@@ -82,8 +83,9 @@
       g_browser_process->platform_part()
           ->GetTimezoneResolverManager()
           ->TimeZoneResolverAllowedByTimeZoneConfigData();
-  if (new_value == current_value)
+  if (new_value == current_value) {
     return SetPrefResult::SUCCESS;
+  }
 
   profile_->GetPrefs()->SetInteger(
       ::prefs::kResolveTimezoneByGeolocationMethod,
diff --git a/chrome/browser/extensions/api/settings_private/generated_pref.cc b/chrome/browser/extensions/api/settings_private/generated_pref.cc
index c81df9ff..adbc6cd 100644
--- a/chrome/browser/extensions/api/settings_private/generated_pref.cc
+++ b/chrome/browser/extensions/api/settings_private/generated_pref.cc
@@ -28,8 +28,9 @@
 }
 
 void GeneratedPref::NotifyObservers(const std::string& pref_name) {
-  for (Observer& observer : observers_)
+  for (Observer& observer : observers_) {
     observer.OnGeneratedPrefChanged(pref_name);
+  }
 }
 
 /* static */
diff --git a/chrome/browser/extensions/api/settings_private/generated_prefs.cc b/chrome/browser/extensions/api/settings_private/generated_prefs.cc
index e723dbb..5463ee4e 100644
--- a/chrome/browser/extensions/api/settings_private/generated_prefs.cc
+++ b/chrome/browser/extensions/api/settings_private/generated_prefs.cc
@@ -41,8 +41,9 @@
 std::optional<api::settings_private::PrefObject> GeneratedPrefs::GetPref(
     const std::string& pref_name) {
   GeneratedPref* impl = FindPrefImpl(pref_name);
-  if (!impl)
+  if (!impl) {
     return std::nullopt;
+  }
 
   return impl->GetPrefObject();
 }
@@ -50,8 +51,9 @@
 SetPrefResult GeneratedPrefs::SetPref(const std::string& pref_name,
                                       const base::Value* value) {
   GeneratedPref* impl = FindPrefImpl(pref_name);
-  if (!impl)
+  if (!impl) {
     return SetPrefResult::PREF_NOT_FOUND;
+  }
 
   return impl->SetPref(value);
 }
@@ -67,8 +69,9 @@
 void GeneratedPrefs::RemoveObserver(const std::string& pref_name,
                                     GeneratedPref::Observer* observer) {
   GeneratedPref* impl = FindPrefImpl(pref_name);
-  if (!impl)
+  if (!impl) {
     return;
+  }
 
   impl->RemoveObserver(observer);
 }
@@ -80,12 +83,14 @@
 }
 
 GeneratedPref* GeneratedPrefs::FindPrefImpl(const std::string& pref_name) {
-  if (prefs_.empty())
+  if (prefs_.empty()) {
     CreatePrefs();
+  }
 
   const PrefsMap::const_iterator it = prefs_.find(pref_name);
-  if (it == prefs_.end())
+  if (it == prefs_.end()) {
     return nullptr;
+  }
 
   return it->second.get();
 }
diff --git a/chrome/browser/extensions/api/settings_private/settings_private_delegate.cc b/chrome/browser/extensions/api/settings_private/settings_private_delegate.cc
index 28113210..3f2e61cb 100644
--- a/chrome/browser/extensions/api/settings_private/settings_private_delegate.cc
+++ b/chrome/browser/extensions/api/settings_private/settings_private_delegate.cc
@@ -33,8 +33,9 @@
     const std::string& name) {
   std::optional<api::settings_private::PrefObject> pref =
       prefs_util_->GetPref(name);
-  if (!pref)
+  if (!pref) {
     return std::nullopt;
+  }
   return pref->ToValue();
 }
 
@@ -61,8 +62,9 @@
   // Zoom level prefs aren't available for off-the-record profiles (like guest
   // mode on Chrome OS). The setting isn't visible to users anyway, so return a
   // default value.
-  if (profile_->IsOffTheRecord())
+  if (profile_->IsOffTheRecord()) {
     return base::Value(0.0);
+  }
   double zoom = blink::ZoomLevelToZoomFactor(
       profile_->GetZoomLevelPrefs()->GetDefaultZoomLevelPref());
   return base::Value(zoom);
@@ -71,8 +73,9 @@
 settings_private::SetPrefResult SettingsPrivateDelegate::SetDefaultZoom(
     double zoom) {
   // See comment in GetDefaultZoom().
-  if (profile_->IsOffTheRecord())
+  if (profile_->IsOffTheRecord()) {
     return settings_private::SetPrefResult::PREF_NOT_MODIFIABLE;
+  }
   double zoom_factor = blink::ZoomFactorToZoomLevel(zoom);
   profile_->GetZoomLevelPrefs()->SetDefaultZoomLevelPref(zoom_factor);
   return settings_private::SetPrefResult::SUCCESS;
diff --git a/chrome/browser/extensions/api/settings_private/settings_private_event_router.cc b/chrome/browser/extensions/api/settings_private/settings_private_event_router.cc
index 02aaed26d..9465ba8 100644
--- a/chrome/browser/extensions/api/settings_private/settings_private_event_router.cc
+++ b/chrome/browser/extensions/api/settings_private/settings_private_event_router.cc
@@ -55,10 +55,11 @@
     settings_private::GeneratedPrefs* generated_prefs =
         settings_private::GeneratedPrefsFactory::GetForBrowserContext(context_);
     for (const auto& it : keys) {
-      if (generated_prefs && generated_prefs->HasPref(it.first))
+      if (generated_prefs && generated_prefs->HasPref(it.first)) {
         generated_prefs->RemoveObserver(it.first, this);
-      else if (!prefs_util_->IsCrosSetting(it.first))
+      } else if (!prefs_util_->IsCrosSetting(it.first)) {
         FindRegistrarForPref(it.first)->Remove(it.first);
+      }
     }
   }
   listening_ = false;
@@ -156,8 +157,9 @@
       prefs_util_->GetPref(pref_name);
 
   std::vector<api::settings_private::PrefObject> prefs;
-  if (pref_object)
+  if (pref_object) {
     prefs.push_back(std::move(*pref_object));
+  }
 
   auto args(api::settings_private::OnPrefsChanged::Create(prefs));
 
diff --git a/chrome/browser/extensions/api/side_panel/side_panel_service.cc b/chrome/browser/extensions/api/side_panel/side_panel_service.cc
index 595840a..5474809 100644
--- a/chrome/browser/extensions/api/side_panel/side_panel_service.cc
+++ b/chrome/browser/extensions/api/side_panel/side_panel_service.cc
@@ -115,8 +115,9 @@
   // The specific `tab_id` may have already been saved.
   if (tab_id != default_tab_id) {
     auto specific_tab_options = tab_panel_options.find(tab_id);
-    if (specific_tab_options != tab_panel_options.end())
+    if (specific_tab_options != tab_panel_options.end()) {
       return specific_tab_options->second.Clone();
+    }
   }
 
   // Fall back to the default tab if no tab ID was specified or entries for the
@@ -159,8 +160,9 @@
       };
 
   TabId tab_id = SessionID::InvalidValue().id();
-  if (options.tab_id)
+  if (options.tab_id) {
     tab_id = *options.tab_id;
+  }
   TabPanelOptions& extension_panel_options = panels_[extension.id()];
   auto it = extension_panel_options.find(tab_id);
 
diff --git a/chrome/browser/extensions/api/storage/managed_value_store_cache.cc b/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
index 6c5eb2cc..b538fec 100644
--- a/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
+++ b/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
@@ -132,8 +132,9 @@
   // becomes ready. Wait until all of them are ready before registering the
   // schemas of managed extensions, so that the policy loaders are reloaded at
   // most once.
-  if (!ExtensionSystem::Get(profile_)->ready().is_signaled())
+  if (!ExtensionSystem::Get(profile_)->ready().is_signaled()) {
     return;
+  }
   ExtensionSet added;
   added.Insert(extension);
   LoadSchemas(std::move(added));
@@ -143,8 +144,9 @@
     content::BrowserContext* browser_context,
     const Extension* extension,
     extensions::UninstallReason reason) {
-  if (!ExtensionSystem::Get(profile_)->ready().is_signaled())
+  if (!ExtensionSystem::Get(profile_)->ready().is_signaled()) {
     return;
+  }
   if (extension && UsesManagedStorage(extension)) {
     schema_registry_->UnregisterComponent(
         policy::PolicyNamespace(policy_domain_, extension->id()));
@@ -162,11 +164,13 @@
   ExtensionSet::const_iterator it = added.begin();
   while (it != added.end()) {
     std::string to_remove;
-    if (!UsesManagedStorage(it->get()))
+    if (!UsesManagedStorage(it->get())) {
       to_remove = (*it)->id();
+    }
     ++it;
-    if (!to_remove.empty())
+    if (!to_remove.empty()) {
       added.Remove(to_remove);
+    }
   }
 
   GetExtensionFileTaskRunner()->PostTask(
@@ -252,8 +256,9 @@
   extension_tracker_ =
       std::make_unique<ExtensionTracker>(&profile, policy_domain_);
 
-  if (policy_service_->IsInitializationComplete(policy_domain_))
+  if (policy_service_->IsInitializationComplete(policy_domain_)) {
     OnPolicyServiceInitialized(policy_domain_);
+  }
 }
 
 ManagedValueStoreCache::~ManagedValueStoreCache() {
@@ -297,8 +302,9 @@
   // It's possible that the store exists, but hasn't been loaded yet
   // (because the extension is unloaded, for example). Open the database to
   // clear it if it exists.
-  if (!HasStore(extension_id))
+  if (!HasStore(extension_id)) {
     return;
+  }
   GetOrCreateStore(extension_id).DeleteStorage();
   store_map_.erase(extension_id);
 }
@@ -307,8 +313,9 @@
     policy::PolicyDomain domain) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
 
-  if (domain != policy_domain_)
+  if (domain != policy_domain_) {
     return;
+  }
 
   // The PolicyService now has all the initial policies ready. Send policy
   // for all the managed extensions to their backing stores now.
@@ -389,8 +396,9 @@
 PolicyValueStore& ManagedValueStoreCache::GetOrCreateStore(
     const ExtensionId& extension_id) {
   const auto& it = store_map_.find(extension_id);
-  if (it != store_map_.end())
+  if (it != store_map_.end()) {
     return *it->second;
+  }
 
   // Create the store now, and serve the cached policy until the PolicyService
   // sends updated values.
diff --git a/chrome/browser/extensions/api/storage/policy_value_store.cc b/chrome/browser/extensions/api/storage/policy_value_store.cc
index 8fc7c62..fb990f60 100644
--- a/chrome/browser/extensions/api/storage/policy_value_store.cc
+++ b/chrome/browser/extensions/api/storage/policy_value_store.cc
@@ -74,8 +74,9 @@
   // anymore.
   std::vector<std::string> removed_keys;
   for (auto kv : previous_policy) {
-    if (!current_policy.Find(kv.first))
+    if (!current_policy.Find(kv.first)) {
       removed_keys.push_back(kv.first);
+    }
   }
 
   value_store::ValueStoreChangeList changes;
diff --git a/chrome/browser/extensions/api/storage/settings_sync_processor.cc b/chrome/browser/extensions/api/storage/settings_sync_processor.cc
index 71b8589f..19c9317 100644
--- a/chrome/browser/extensions/api/storage/settings_sync_processor.cc
+++ b/chrome/browser/extensions/api/storage/settings_sync_processor.cc
@@ -82,13 +82,15 @@
     }
   }
 
-  if (sync_changes.empty())
+  if (sync_changes.empty()) {
     return std::nullopt;
+  }
 
   std::optional<syncer::ModelError> error =
       sync_processor_->ProcessSyncChanges(FROM_HERE, sync_changes);
-  if (error.has_value())
+  if (error.has_value()) {
     return error;
+  }
 
   synced_keys_.insert(added_keys.begin(), added_keys.end());
   for (const auto& deleted_key : deleted_keys) {
@@ -104,10 +106,11 @@
   CHECK(initialized_) << "Init not called";
 
   for (const auto& i : changes) {
-    if (i.new_value)
+    if (i.new_value) {
       synced_keys_.insert(i.key);
-    else
+    } else {
       synced_keys_.erase(i.key);
+    }
   }
 }
 
diff --git a/chrome/browser/extensions/api/storage/settings_sync_unittest.cc b/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
index a5e163a..4264582 100644
--- a/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
+++ b/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
@@ -140,8 +140,9 @@
                                  const std::string& key) {
     std::vector<SettingSyncData*> matching_changes;
     for (const std::unique_ptr<SettingSyncData>& change : changes_) {
-      if (change->extension_id() == extension_id && change->key() == key)
+      if (change->extension_id() == extension_id && change->key() == key) {
         matching_changes.push_back(change.get());
+      }
     }
     if (matching_changes.empty()) {
       ADD_FAILURE() << "No matching changes for " << extension_id << "/" <<
@@ -243,8 +244,9 @@
       std::unique_ptr<SettingSyncData> sync_data(new SettingSyncData(data));
       std::unique_ptr<SettingSyncDataList>& list_for_extension =
           as_map[sync_data->extension_id()];
-      if (!list_for_extension)
+      if (!list_for_extension) {
         list_for_extension = std::make_unique<SettingSyncDataList>();
+      }
       list_for_extension->push_back(std::move(sync_data));
     }
     return as_map;
diff --git a/chrome/browser/extensions/api/storage/settings_sync_util.cc b/chrome/browser/extensions/api/storage/settings_sync_util.cc
index da8eace..e453679 100644
--- a/chrome/browser/extensions/api/storage/settings_sync_util.cc
+++ b/chrome/browser/extensions/api/storage/settings_sync_util.cc
@@ -29,8 +29,9 @@
     base::WeakPtr<SyncValueStoreCache> sync_cache,
     syncer::DataType type) {
   DCHECK(IsOnBackendSequence());
-  if (!sync_cache)
+  if (!sync_cache) {
     return nullptr;
+  }
   return sync_cache->GetSyncableService(type)->AsWeakPtr();
 }
 
diff --git a/chrome/browser/extensions/api/storage/sync_storage_backend.cc b/chrome/browser/extensions/api/storage/sync_storage_backend.cc
index 4a7dd29..98e2663 100644
--- a/chrome/browser/extensions/api/storage/sync_storage_backend.cc
+++ b/chrome/browser/extensions/api/storage/sync_storage_backend.cc
@@ -105,8 +105,9 @@
     std::optional<syncer::ModelError> error =
         raw_syncable_storage->StartSyncing(
             std::move(sync_data), CreateSettingsSyncProcessor(extension_id));
-    if (error.has_value())
+    if (error.has_value()) {
       raw_syncable_storage->StopSyncing();
+    }
   }
   return raw_syncable_storage;
 }
@@ -194,8 +195,9 @@
                                     CreateSettingsSyncProcessor(extension_id));
     }
 
-    if (error.has_value())
+    if (error.has_value()) {
       storage->StopSyncing();
+    }
   }
 
   // Eagerly create and init the rest of the storage areas that have sync data.
@@ -222,8 +224,9 @@
   for (const syncer::SyncChange& change : sync_changes) {
     std::unique_ptr<SettingSyncData> data(new SettingSyncData(change));
     SettingSyncDataList*& group = grouped_sync_data[data->extension_id()];
-    if (!group)
+    if (!group) {
       group = new SettingSyncDataList();
+    }
     group->push_back(std::move(data));
   }
 
@@ -233,8 +236,9 @@
         GetOrCreateStorageWithSyncData(group.first, EmptyDict());
     std::optional<syncer::ModelError> error =
         storage->ProcessSyncChanges(base::WrapUnique(group.second));
-    if (error.has_value())
+    if (error.has_value()) {
       storage->StopSyncing();
+    }
   }
 
   return std::nullopt;
diff --git a/chrome/browser/extensions/api/storage/syncable_settings_storage.cc b/chrome/browser/extensions/api/storage/syncable_settings_storage.cc
index 8d7eac02..cec445a 100644
--- a/chrome/browser/extensions/api/storage/syncable_settings_storage.cc
+++ b/chrome/browser/extensions/api/storage/syncable_settings_storage.cc
@@ -97,8 +97,9 @@
     WriteOptions options, const std::string& key, const base::Value& value) {
   DCHECK(IsOnBackendSequence());
   WriteResult result = HandleResult(delegate_->Set(options, key, value));
-  if (!result.status().ok())
+  if (!result.status().ok()) {
     return result;
+  }
   SyncResultIfEnabled(result);
   return result;
 }
@@ -108,8 +109,9 @@
     const base::DictValue& values) {
   DCHECK(IsOnBackendSequence());
   WriteResult result = HandleResult(delegate_->Set(options, values));
-  if (!result.status().ok())
+  if (!result.status().ok()) {
     return result;
+  }
   SyncResultIfEnabled(result);
   return result;
 }
@@ -118,8 +120,9 @@
     const std::string& key) {
   DCHECK(IsOnBackendSequence());
   WriteResult result = HandleResult(delegate_->Remove(key));
-  if (!result.status().ok())
+  if (!result.status().ok()) {
     return result;
+  }
   SyncResultIfEnabled(result);
   return result;
 }
@@ -128,8 +131,9 @@
     const std::vector<std::string>& keys) {
   DCHECK(IsOnBackendSequence());
   WriteResult result = HandleResult(delegate_->Remove(keys));
-  if (!result.status().ok())
+  if (!result.status().ok()) {
     return result;
+  }
   SyncResultIfEnabled(result);
   return result;
 }
@@ -137,22 +141,25 @@
 ValueStore::WriteResult SyncableSettingsStorage::Clear() {
   DCHECK(IsOnBackendSequence());
   WriteResult result = HandleResult(delegate_->Clear());
-  if (!result.status().ok())
+  if (!result.status().ok()) {
     return result;
+  }
   SyncResultIfEnabled(result);
   return result;
 }
 
 void SyncableSettingsStorage::SyncResultIfEnabled(
     const ValueStore::WriteResult& result) {
-  if (result.changes().empty())
+  if (result.changes().empty()) {
     return;
+  }
 
   if (sync_processor_.get()) {
     std::optional<syncer::ModelError> error =
         sync_processor_->SendChanges(result.changes());
-    if (error.has_value())
+    if (error.has_value()) {
       StopSyncing();
+    }
   } else {
     // Tell sync to try and start soon, because syncable changes to sync_type_
     // have started happening. This will cause sync to call us back
@@ -189,8 +196,9 @@
 SyncableSettingsStorage::SendLocalSettingsToSync(base::DictValue local_state) {
   DCHECK(IsOnBackendSequence());
 
-  if (local_state.empty())
+  if (local_state.empty()) {
     return std::nullopt;
+  }
 
   // Transform the current settings into a list of sync changes.
   value_store::ValueStoreChangeList changes;
@@ -201,8 +209,9 @@
 
   std::optional<syncer::ModelError> error =
       sync_processor_->SendChanges(std::move(changes));
-  if (error.has_value())
+  if (error.has_value()) {
     StopSyncing();
+  }
   return error;
 }
 
@@ -239,8 +248,9 @@
         std::move(pair.second)));
   }
 
-  if (changes->empty())
+  if (changes->empty()) {
     return std::nullopt;
+  }
   return ProcessSyncChanges(std::move(changes));
 }
 
@@ -332,8 +342,9 @@
                  value_store::ValueStoreChange::ToValue(std::move(changes)));
 
   // TODO(kalman): Something sensible with multiple errors.
-  if (errors.empty())
+  if (errors.empty()) {
     return std::nullopt;
+  }
   return errors[0];
 }
 
diff --git a/chrome/browser/extensions/api/streams_private/streams_private_api.cc b/chrome/browser/extensions/api/streams_private/streams_private_api.cc
index 7a1556e..506fda1 100644
--- a/chrome/browser/extensions/api/streams_private/streams_private_api.cc
+++ b/chrome/browser/extensions/api/streams_private/streams_private_api.cc
@@ -40,8 +40,9 @@
 
   content::WebContents* web_contents =
       content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
-  if (!web_contents)
+  if (!web_contents) {
     return;
+  }
 
   // If the request was for NoStatePrefetch, abort the prefetcher and do not
   // continue. This is because plugins cancel NoStatePrefetch, see
@@ -59,12 +60,14 @@
   const Extension* extension = ExtensionRegistry::Get(browser_context)
                                    ->enabled_extensions()
                                    .GetByID(extension_id);
-  if (!extension)
+  if (!extension) {
     return;
+  }
 
   MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
-  if (!handler->HasPlugin())
+  if (!handler->HasPlugin()) {
     return;
+  }
 
   // If the mime handler uses MimeHandlerViewGuest, the MimeHandlerViewGuest
   // will take ownership of the stream.
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc
index 3024a0c..cfcd8fe 100644
--- a/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc
+++ b/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc
@@ -130,12 +130,15 @@
 
   std::string GetSuffixForTestFlags() const {
     std::string suffix;
-    if (HasFlag(kUseGpu))
+    if (HasFlag(kUseGpu)) {
       suffix += "_comp_gpu";
-    if (HasFlag(kTestThroughWebRTC))
+    }
+    if (HasFlag(kTestThroughWebRTC)) {
       suffix += "_webrtc";
-    if (HasFlag(kSmallWindow))
+    }
+    if (HasFlag(kSmallWindow)) {
       suffix += "_small";
+    }
     // Make sure we always have a story.
     if (suffix.size() == 0) {
       suffix = "_baseline_story";
@@ -153,8 +156,9 @@
     CHECK(success) << "Failed to load test page at: "
                    << test_file.AsUTF8Unsafe();
 
-    if (!HasFlag(kUseGpu))
+    if (!HasFlag(kUseGpu)) {
       UseSoftwareCompositing();
+    }
 
     TabCapturePerformanceTestBase::SetUp();
   }
@@ -223,8 +227,9 @@
     int count = 0;
     for (const auto* begin_event : events_to_analyze) {
       const auto* end_event = begin_event->other_event.get();
-      if (!end_event)
+      if (!end_event) {
         continue;
+      }
       const double latency = end_event->timestamp - begin_event->timestamp;
       sum += latency;
       sqr_sum += latency * latency;
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
index 3ae375a..fdfff1d 100644
--- a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
+++ b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
@@ -78,8 +78,9 @@
     // This method can get duplicate calls if both audio and video were
     // requested, so return early to avoid duplicate dispatching of status
     // change events.
-    if (capture_state_ == next_capture_state)
+    if (capture_state_ == next_capture_state) {
       return;
+    }
 
     capture_state_ = next_capture_state;
     registry_->DispatchStatusChangeEvent(this);
@@ -276,12 +277,14 @@
 
 void TabCaptureRegistry::DispatchStatusChangeEvent(
     const LiveRequest* request) const {
-  if (request->is_anonymous())
+  if (request->is_anonymous()) {
     return;
+  }
 
   EventRouter* router = EventRouter::Get(browser_context_);
-  if (!router)
+  if (!router) {
     return;
+  }
 
   base::ListValue args;
   tab_capture::CaptureInfo info;
@@ -297,8 +300,9 @@
 TabCaptureRegistry::LiveRequest* TabCaptureRegistry::FindRequest(
     const content::WebContents* target_contents) const {
   for (const auto& request : requests_) {
-    if (request->web_contents() == target_contents)
+    if (request->web_contents() == target_contents) {
       return request.get();
+    }
   }
   return nullptr;
 }
diff --git a/chrome/browser/extensions/api/tab_groups/tab_groups_api.cc b/chrome/browser/extensions/api/tab_groups/tab_groups_api.cc
index d6a32fd..e077d25d 100644
--- a/chrome/browser/extensions/api/tab_groups/tab_groups_api.cc
+++ b/chrome/browser/extensions/api/tab_groups/tab_groups_api.cc
@@ -237,8 +237,9 @@
   DCHECK(!id.is_empty());
 
   bool collapsed = visual_data.is_collapsed();
-  if (params->update_properties.collapsed)
+  if (params->update_properties.collapsed) {
     collapsed = *params->update_properties.collapsed;
+  }
 
   tab_groups::TabGroupColorId color = visual_data.color();
   if (params->update_properties.color != api::tab_groups::Color::kNone) {
@@ -246,8 +247,9 @@
   }
 
   std::u16string title = visual_data.title();
-  if (params->update_properties.title)
+  if (params->update_properties.title) {
     title = base::UTF8ToUTF16(*params->update_properties.title);
+  }
 
   if (!ExtensionTabUtil::IsTabStripEditable()) {
     return RespondNow(Error(ExtensionTabUtil::kTabStripNotEditableError));
@@ -273,8 +275,9 @@
   tab_groups::TabGroupVisualData new_visual_data(title, color, collapsed);
   tab_list->SetTabGroupVisualData(id, new_visual_data);
 
-  if (!has_callback())
+  if (!has_callback()) {
     return RespondNow(NoArguments());
+  }
 
   return RespondNow(ArgumentList(api::tab_groups::Get::Results::Create(
       ExtensionTabUtil::CreateTabGroupObject(id, new_visual_data))));
@@ -335,8 +338,9 @@
   }
 #endif  // BUILDFLAG(IS_ANDROID)
 
-  if (!has_callback())
+  if (!has_callback()) {
     return RespondNow(NoArguments());
+  }
 
   auto group_object = ExtensionTabUtil::CreateTabGroupObject(group);
   CHECK(group_object);
diff --git a/chrome/browser/extensions/api/tab_groups/tab_groups_event_router.cc b/chrome/browser/extensions/api/tab_groups/tab_groups_event_router.cc
index fcd126e1..0eaaf51 100644
--- a/chrome/browser/extensions/api/tab_groups/tab_groups_event_router.cc
+++ b/chrome/browser/extensions/api/tab_groups/tab_groups_event_router.cc
@@ -251,8 +251,9 @@
                                          const std::string& event_name,
                                          base::ListValue args) {
   // |event_router_| can be null in tests.
-  if (!event_router_)
+  if (!event_router_) {
     return;
+  }
 
   auto event = std::make_unique<Event>(histogram_value, event_name,
                                        std::move(args), profile_);
diff --git a/chrome/browser/extensions/api/tabs/windows_util.cc b/chrome/browser/extensions/api/tabs/windows_util.cc
index 66b8516a..d96c1f3 100644
--- a/chrome/browser/extensions/api/tabs/windows_util.cc
+++ b/chrome/browser/extensions/api/tabs/windows_util.cc
@@ -76,8 +76,9 @@
 bool CanOperateOnWindow(const ExtensionFunction* function,
                         const extensions::WindowController* controller,
                         extensions::WindowController::TypeFilter filter) {
-  if (filter && !controller->MatchesFilter(filter))
+  if (filter && !controller->MatchesFilter(filter)) {
     return false;
+  }
 
   // TODO(crbug.com/41367902): Remove this.
   bool allow_dev_tools_windows = !!filter;
@@ -87,11 +88,13 @@
     return false;
   }
 
-  if (function->browser_context() == controller->profile())
+  if (function->browser_context() == controller->profile()) {
     return true;
+  }
 
-  if (!function->include_incognito_information())
+  if (!function->include_incognito_information()) {
     return false;
+  }
 
   Profile* profile = Profile::FromBrowserContext(function->browser_context());
   return profile->HasPrimaryOTRProfile() &&
@@ -133,8 +136,9 @@
       if (IsURLAllowedInIncognito((*urls)[i])) {
         i++;
       } else {
-        if (first_url_erased.empty())
+        if (first_url_erased.empty()) {
           first_url_erased = (*urls)[i].spec();
+        }
         urls->erase(urls->begin() + i);
       }
     }
diff --git a/chrome/browser/extensions/api/terminal/terminal_private_api.cc b/chrome/browser/extensions/api/terminal/terminal_private_api.cc
index d72daeb..7a9398b8b 100644
--- a/chrome/browser/extensions/api/terminal/terminal_private_api.cc
+++ b/chrome/browser/extensions/api/terminal/terminal_private_api.cc
@@ -196,8 +196,9 @@
   // sufficient.
   for (vm_tools::cicerone::ContainerFeature feature :
        crostini::GetContainerFeatures()) {
-    if (!result.empty())
+    if (!result.empty()) {
       result += ",";
+    }
     result += base::NumberToString(static_cast<int>(feature));
   }
   return result;
@@ -293,8 +294,9 @@
       extensions::ExtensionsBrowserClient::Get()->GetUserIdHashFromContext(
           browser_context());
   content::WebContents* caller_contents = GetSenderWebContents();
-  if (!caller_contents)
+  if (!caller_contents) {
     return RespondNow(Error("No web contents."));
+  }
 
   // Passing --crosh-command overrides any JS process name.
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -327,8 +329,9 @@
     // command=vmshell: ensure --owner_id, --vm_name, --target_container, --cwd
     // are set, and the specified vm/container is running.
     base::CommandLine cmdline((base::FilePath(kVmShellCommand)));
-    if (!args)
+    if (!args) {
       args.emplace();
+    }
     args->insert(args->begin(), kVmShellCommand);
     base::CommandLine params_args(*args);
     VLOG(1) << "Original cmdline= " << params_args.GetCommandLineString();
@@ -346,8 +349,9 @@
     // Unlike the other switches, this is computed here directly rather than
     // taken from |args|.
     std::string container_features = GetContainerFeaturesArg();
-    if (!container_features.empty())
+    if (!container_features.empty()) {
       cmdline.AppendSwitchASCII(kSwitchContainerFeatures, container_features);
+    }
 
     // Append trailing passthrough args if any.  E.g. `-- vim file.txt`
     auto passthrough_args = params_args.GetArgs();
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
index 0d43300..3e92237 100644
--- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
+++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -80,8 +80,9 @@
 ui::TextInputClient* GetFocusedTextInputClient() {
   ui::InputMethod* input_method =
       ash::IMEBridge::Get()->GetInputContextHandler()->GetInputMethod();
-  if (!input_method)
+  if (!input_method) {
     return nullptr;
+  }
 
   return input_method->GetTextInputClient();
 }
@@ -110,12 +111,13 @@
                       int modifiers,
                       aura::WindowTreeHost* host) {
   ui::EventType event_type;
-  if (type == kKeyDown)
+  if (type == kKeyDown) {
     event_type = ui::EventType::kKeyPressed;
-  else if (type == kKeyUp)
+  } else if (type == kKeyUp) {
     event_type = ui::EventType::kKeyReleased;
-  else
+  } else {
     return false;
+  }
 
   ui::KeyboardCode code = static_cast<ui::KeyboardCode>(key_code);
 
@@ -130,16 +132,18 @@
 
       ui::KeyEvent char_event = ui::KeyEvent::FromCharacter(
           key_value, code, ui::DomCode::NONE, ui::EF_NONE);
-      if (tic)
+      if (tic) {
         tic->InsertChar(char_event);
+      }
       SendProcessKeyEvent(ui::EventType::kKeyReleased, host);
     }
     return true;
   }
 
   ui::DomCode dom_code = ui::KeycodeConverter::CodeStringToDomCode(key_name);
-  if (dom_code == ui::DomCode::NONE)
+  if (dom_code == ui::DomCode::NONE) {
     dom_code = ui::UsLayoutKeyboardCodeToDomCode(code);
+  }
   CHECK(dom_code != ui::DomCode::NONE);
 
   ui::KeyEvent event(event_type, code, dom_code, modifiers);
@@ -194,15 +198,17 @@
 ChromeVirtualKeyboardDelegate::~ChromeVirtualKeyboardDelegate() {
   ash::ClipboardHistoryController* clipboard_history_controller =
       ash::ClipboardHistoryController::Get();
-  if (clipboard_history_controller)
+  if (clipboard_history_controller) {
     clipboard_history_controller->RemoveObserver(this);
+  }
 }
 
 void ChromeVirtualKeyboardDelegate::GetKeyboardConfig(
     OnKeyboardSettingsCallback on_settings_callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  if (!audio_system_)
+  if (!audio_system_) {
     audio_system_ = content::CreateAudioSystemForAudioService();
+  }
   audio_system_->HasInputDevices(
       base::BindOnce(&ChromeVirtualKeyboardDelegate::OnHasInputDevices,
                      weak_this_, std::move(on_settings_callback)));
@@ -217,8 +223,9 @@
 bool ChromeVirtualKeyboardDelegate::HideKeyboard() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
-  if (!keyboard_client->is_keyboard_enabled())
+  if (!keyboard_client->is_keyboard_enabled()) {
     return false;
+  }
 
   // Pass HIDE_REASON_MANUAL since calls to HideKeyboard as part of this API
   // would be user generated.
@@ -229,8 +236,9 @@
 bool ChromeVirtualKeyboardDelegate::InsertText(const std::u16string& text) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   ui::TextInputClient* tic = GetFocusedTextInputClient();
-  if (!tic || tic->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
+  if (!tic || tic->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) {
     return false;
+  }
 
   tic->InsertText(
       text,
@@ -245,8 +253,9 @@
 }
 
 void ChromeVirtualKeyboardDelegate::SetHotrodKeyboard(bool enable) {
-  if (g_hotrod_keyboard_enabled == enable)
+  if (g_hotrod_keyboard_enabled == enable) {
     return;
+  }
 
   g_hotrod_keyboard_enabled = enable;
 
@@ -259,8 +268,9 @@
 bool ChromeVirtualKeyboardDelegate::LockKeyboard(bool state) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
-  if (!keyboard_client->is_keyboard_enabled())
+  if (!keyboard_client->is_keyboard_enabled()) {
     return false;
+  }
 
   keyboard_client->SetKeyboardLocked(state);
   return true;
@@ -281,8 +291,9 @@
 bool ChromeVirtualKeyboardDelegate::ShowLanguageSettings() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
-  if (keyboard_client->is_keyboard_enabled())
+  if (keyboard_client->is_keyboard_enabled()) {
     keyboard_client->HideKeyboard(ash::HideReason::kUser);
+  }
 
   base::RecordAction(
       base::UserMetricsAction("VirtualKeyboard.OpenLanguageSettings"));
@@ -295,8 +306,9 @@
 bool ChromeVirtualKeyboardDelegate::ShowSuggestionSettings() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
-  if (keyboard_client->is_keyboard_enabled())
+  if (keyboard_client->is_keyboard_enabled()) {
     keyboard_client->HideKeyboard(ash::HideReason::kUser);
+  }
 
   base::RecordAction(
       base::UserMetricsAction("VirtualKeyboard.OpenSuggestionSettings"));
@@ -311,8 +323,9 @@
     gfx::Rect target_bounds,
     OnSetModeCallback on_set_mode_callback) {
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
-  if (!keyboard_client->is_keyboard_enabled())
+  if (!keyboard_client->is_keyboard_enabled()) {
     return false;
+  }
 
   keyboard_client->SetContainerType(ConvertKeyboardModeToContainerType(mode),
                                     target_bounds,
@@ -323,8 +336,9 @@
 bool ChromeVirtualKeyboardDelegate::SetOccludedBounds(
     const std::vector<gfx::Rect>& bounds) {
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
-  if (!keyboard_client->is_keyboard_enabled())
+  if (!keyboard_client->is_keyboard_enabled()) {
     return false;
+  }
 
   keyboard_client->SetOccludedBounds(bounds);
   return true;
@@ -333,8 +347,9 @@
 bool ChromeVirtualKeyboardDelegate::SetHitTestBounds(
     const std::vector<gfx::Rect>& bounds) {
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
-  if (!keyboard_client->is_keyboard_enabled())
+  if (!keyboard_client->is_keyboard_enabled()) {
     return false;
+  }
 
   keyboard_client->SetHitTestBounds(bounds);
   return true;
@@ -343,8 +358,9 @@
 bool ChromeVirtualKeyboardDelegate::SetAreaToRemainOnScreen(
     const gfx::Rect& bounds) {
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
-  if (!keyboard_client->is_keyboard_enabled())
+  if (!keyboard_client->is_keyboard_enabled()) {
     return false;
+  }
 
   return keyboard_client->SetAreaToRemainOnScreen(bounds);
 }
@@ -352,8 +368,9 @@
 bool ChromeVirtualKeyboardDelegate::SetWindowBoundsInScreen(
     const gfx::Rect& bounds_in_screen) {
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
-  if (!keyboard_client->is_keyboard_enabled())
+  if (!keyboard_client->is_keyboard_enabled()) {
     return false;
+  }
 
   return keyboard_client->SetWindowBoundsInScreen(bounds_in_screen);
 }
@@ -390,8 +407,9 @@
     const std::string& clipboard_item_id) {
   ash::ClipboardHistoryController* clipboard_history_controller =
       ash::ClipboardHistoryController::Get();
-  if (!clipboard_history_controller)
+  if (!clipboard_history_controller) {
     return false;
+  }
 
   return clipboard_history_controller->PasteClipboardItemById(
       clipboard_item_id, ui::EF_NONE,
@@ -402,8 +420,9 @@
     const std::string& clipboard_item_id) {
   ash::ClipboardHistoryController* clipboard_history_controller =
       ash::ClipboardHistoryController::Get();
-  if (!clipboard_history_controller)
+  if (!clipboard_history_controller) {
     return false;
+  }
 
   return clipboard_history_controller->DeleteClipboardItemById(
       clipboard_item_id);
@@ -414,8 +433,9 @@
   auto* keyboard_client = ChromeKeyboardControllerClient::Get();
   // Since controller will be destroyed when system switch from VK to
   // physical keyboard, return true to avoid unnecessary exception.
-  if (!keyboard_client->is_keyboard_enabled())
+  if (!keyboard_client->is_keyboard_enabled()) {
     return true;
+  }
 
   keyboard_client->SetDraggableArea(
       gfx::Rect(rect.left, rect.top, rect.width, rect.height));
@@ -460,13 +480,15 @@
 
   EventRouter* router = GetRouterForEventName(
       browser_context_, keyboard_api::OnClipboardHistoryChanged::kEventName);
-  if (!router)
+  if (!router) {
     return;
+  }
 
   ash::ClipboardHistoryController* clipboard_history_controller =
       ash::ClipboardHistoryController::Get();
-  if (!clipboard_history_controller)
+  if (!clipboard_history_controller) {
     return;
+  }
 
   auto item_ids = clipboard_history_controller->GetHistoryItemIds();
 
@@ -533,8 +555,9 @@
 
   EventRouter* router = GetRouterForEventName(
       browser_context_, keyboard_api::OnKeyboardConfigChanged::kEventName);
-  if (!router)
+  if (!router) {
     return;
+  }
 
   base::ListValue event_args;
   event_args.Append(std::move(*settings));
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
index 412c427..d86d324 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
@@ -52,8 +52,9 @@
     ExtensionApiFrameIdMap::DocumentId document_id =
         ExtensionApiFrameIdMap::DocumentIdFromString(
             *params->details.document_id);
-    if (!document_id)
+    if (!document_id) {
       return RespondNow(Error("Invalid documentId."));
+    }
 
     // Note that we will globally find a RenderFrameHost but validate that
     // we are in the right context still as we may be in the wrong profile
@@ -62,8 +63,9 @@
         ExtensionApiFrameIdMap::Get()->GetRenderFrameHostByDocumentId(
             document_id);
 
-    if (!render_frame_host)
+    if (!render_frame_host) {
       return RespondNow(WithArguments(base::Value()));
+    }
 
     content::WebContents* web_contents =
         content::WebContents::FromRenderFrameHost(render_frame_host);
@@ -110,12 +112,14 @@
       render_frame_host
           ? FrameNavigationState::GetForCurrentDocument(render_frame_host)
           : nullptr;
-  if (!frame_navigation_state)
+  if (!frame_navigation_state) {
     return RespondNow(WithArguments(base::Value()));
+  }
 
   GURL frame_url = frame_navigation_state->GetUrl();
-  if (!FrameNavigationState::IsValidUrl(frame_url))
+  if (!FrameNavigationState::IsValidUrl(frame_url)) {
     return RespondNow(WithArguments(base::Value()));
+  }
 
   GetFrame::Results::Details frame_details;
   frame_details.url = frame_url.spec();
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.cc
index 2ead047..36b6bcd 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.cc
@@ -147,14 +147,18 @@
   dict.Set(web_navigation_api_constants::kTransitionTypeKey,
            transition_type_string);
   base::ListValue qualifiers;
-  if (transition_type & ui::PAGE_TRANSITION_CLIENT_REDIRECT)
+  if (transition_type & ui::PAGE_TRANSITION_CLIENT_REDIRECT) {
     qualifiers.Append("client_redirect");
-  if (transition_type & ui::PAGE_TRANSITION_SERVER_REDIRECT)
+  }
+  if (transition_type & ui::PAGE_TRANSITION_SERVER_REDIRECT) {
     qualifiers.Append("server_redirect");
-  if (transition_type & ui::PAGE_TRANSITION_FORWARD_BACK)
+  }
+  if (transition_type & ui::PAGE_TRANSITION_FORWARD_BACK) {
     qualifiers.Append("forward_back");
-  if (transition_type & ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)
+  }
+  if (transition_type & ui::PAGE_TRANSITION_FROM_ADDRESS_BAR) {
     qualifiers.Append("from_address_bar");
+  }
   dict.Set(web_navigation_api_constants::kTransitionQualifiersKey,
            std::move(qualifiers));
   dict.Set(web_navigation_api_constants::kTimeStampKey,
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
index 051ed3c..509017a 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
@@ -155,11 +155,13 @@
   event_router->AddEventListener(
       &profile_, ext_id, ext_id, kEventName, kSubEventName1,
       WebRequestEventRouter::RequestFilter(), 0, 1 /* render_process_id */, 0,
-      extensions::kMainThreadId, blink::mojom::kInvalidServiceWorkerVersionId);
+      extensions::kMainThreadId, blink::mojom::kInvalidServiceWorkerVersionId,
+      /*is_lazy=*/false);
   event_router->AddEventListener(
       &profile_, ext_id, ext_id, kEventName, kSubEventName2,
       WebRequestEventRouter::RequestFilter(), 0, 1 /* render_process_id */, 0,
-      extensions::kMainThreadId, blink::mojom::kInvalidServiceWorkerVersionId);
+      extensions::kMainThreadId, blink::mojom::kInvalidServiceWorkerVersionId,
+      /*is_lazy=*/false);
   EXPECT_EQ(2u,
             event_router->GetListenerCountForTesting(&profile_, kEventName));
 
@@ -198,11 +200,13 @@
   event_router->AddEventListener(
       &profile_, ext_id, ext_id, kEventName, kSubEventName,
       WebRequestEventRouter::RequestFilter(), 0, 1 /* render_process_id */, 0,
-      extensions::kMainThreadId, blink::mojom::kInvalidServiceWorkerVersionId);
+      extensions::kMainThreadId, blink::mojom::kInvalidServiceWorkerVersionId,
+      /*is_lazy=*/false);
   event_router->AddEventListener(
       &profile_, ext_id, ext_id, kEventName, kSubEventName,
       WebRequestEventRouter::RequestFilter(), 0, 2 /* render_process_id */, 0,
-      extensions::kMainThreadId, blink::mojom::kInvalidServiceWorkerVersionId);
+      extensions::kMainThreadId, blink::mojom::kInvalidServiceWorkerVersionId,
+      /*is_lazy=*/false);
   event_router->IncrementExtraHeadersListenerCount(&profile_);
   EXPECT_EQ(2u,
             event_router->GetListenerCountForTesting(&profile_, kEventName));
@@ -228,11 +232,13 @@
   event_router->AddEventListener(
       otr_profile, ext_id, ext_id, kEventName, kSubEventName,
       WebRequestEventRouter::RequestFilter(), 0, 1 /* render_process_id */, 0,
-      extensions::kMainThreadId, blink::mojom::kInvalidServiceWorkerVersionId);
+      extensions::kMainThreadId, blink::mojom::kInvalidServiceWorkerVersionId,
+      /*is_lazy=*/false);
   event_router->AddEventListener(
       otr_profile, ext_id, ext_id, kEventName, kSubEventName,
       WebRequestEventRouter::RequestFilter(), 0, 2 /* render_process_id */, 0,
-      extensions::kMainThreadId, blink::mojom::kInvalidServiceWorkerVersionId);
+      extensions::kMainThreadId, blink::mojom::kInvalidServiceWorkerVersionId,
+      /*is_lazy=*/false);
   event_router->IncrementExtraHeadersListenerCount(otr_profile);
   EXPECT_EQ(2u,
             event_router->GetListenerCountForTesting(otr_profile, kEventName));
@@ -1579,8 +1585,9 @@
   expected_cookies.insert(
       "uBound5=value12; max-age=600; expires=" + cookie_expiration+ "; secure");
   std::set<std::string> actual_cookies;
-  while (new_headers1->EnumerateHeader(&iter, "Set-Cookie", &cookie_string))
+  while (new_headers1->EnumerateHeader(&iter, "Set-Cookie", &cookie_string)) {
     actual_cookies.insert(cookie_string);
+  }
   EXPECT_EQ(expected_cookies, actual_cookies);
 }
 
@@ -1714,8 +1721,9 @@
   EXPECT_TRUE(preserve_fragment_on_redirect_url3.is_empty());
   iter = 0;
   std::multimap<std::string, std::string> actual3;
-  while (new_headers3->EnumerateHeaderLines(&iter, &name, &value))
+  while (new_headers3->EnumerateHeaderLines(&iter, &name, &value)) {
     actual3.emplace(name, value);
+  }
   std::multimap<std::string, std::string> expected3;
   expected3.emplace("Key2", "Value4");
   expected3.emplace("Key1", "Value1");
@@ -1766,8 +1774,9 @@
 
   iter = 0;
   std::multimap<std::string, std::string> actual4;
-  while (new_headers4->EnumerateHeaderLines(&iter, &name, &value))
+  while (new_headers4->EnumerateHeaderLines(&iter, &name, &value)) {
     actual4.emplace(name, value);
+  }
   std::multimap<std::string, std::string> expected4;
 
   expected4.emplace("Key2", "Value3");
@@ -2018,8 +2027,9 @@
   std::string name;
   std::string value;
   std::multimap<std::string, std::string> actual_headers;
-  while (new_headers->EnumerateHeaderLines(&iter, &name, &value))
+  while (new_headers->EnumerateHeaderLines(&iter, &name, &value)) {
     actual_headers.emplace(name, value);
+  }
 
   std::multimap<std::string, std::string> expected_headers;
   // An append operation should allow subsequent appends, but not any other
@@ -2124,8 +2134,9 @@
   std::string name;
   std::string value;
   std::multimap<std::string, std::string> actual_headers;
-  while (new_headers->EnumerateHeaderLines(&iter, &name, &value))
+  while (new_headers->EnumerateHeaderLines(&iter, &name, &value)) {
     actual_headers.emplace(name, value);
+  }
 
   std::multimap<std::string, std::string> expected_headers;
   expected_headers.emplace("connection", "dnr_action_1");
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index 220f747..5f1f05f 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -4872,8 +4872,9 @@
         self.numScriptRequests = 0;
         self.numUUIDInPackageScriptRequests = 0;
         chrome.webRequest.onBeforeRequest.addListener(function(details) {
-          if (details.url.includes('test.html'))
+          if (details.url.includes('test.html')) {
             self.numMainResourceRequests++;
+          }
           else if (details.url.includes('web_bundle.wbn'))
             self.numWebBundleRequests++;
           else if (details.url.includes('test.js'))
@@ -5462,8 +5463,9 @@
   test_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
                      base::StringPrintf(R"(
         chrome.webRequest.onBeforeRequest.addListener(function(details) {
-          if (!details.url.includes('redirect.wbn'))
+          if (!details.url.includes('redirect.wbn')) {
             return;
+          }
           const redirectUrl =
               details.url.replace('redirect.wbn', 'redirected.wbn');
           return {redirectUrl};
@@ -7054,8 +7056,9 @@
          // test.
          async function flushStorage() {
            console.assert(!storageComplete);
-           if (!isUsingStorage)
+           if (!isUsingStorage) {
              return;
+           }
            await new Promise((resolve) => {
              storageComplete = resolve;
            });
@@ -7070,8 +7073,9 @@
                requestCount++;
                await chrome.storage.local.set({requestCount});
                isUsingStorage = false;
-               if (storageComplete)
+               if (storageComplete) {
                  storageComplete();
+               }
                chrome.test.sendMessage('event received');
              },
              {urls: ['<all_urls>'], types: ['main_frame']});)";
@@ -7141,23 +7145,23 @@
   EXPECT_EQ(2, get_request_count());
 }
 
-class ManifestV3WebRequestApiTestWithAlternativeAddListener
+class ManifestV3WebRequestApiTestWithEventRouterPersistence
     : public ManifestV3WebRequestApiTest {
  public:
-  ManifestV3WebRequestApiTestWithAlternativeAddListener() {
+  ManifestV3WebRequestApiTestWithEventRouterPersistence() {
     scoped_feature_list_.InitAndEnableFeature(
-        extensions_features::kWebRequestAlternativeAddListener);
+        extensions_features::kWebRequestPersistFilteredEventsViaEventRouter);
   }
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-// Test that, when the `WebRequestAlternativeAddListener` feature flag is
-// enabled, adding a listener right after an extension has been unloaded, but
-// before its renderer has been shut down, doesn't cause a CHECK failure in
-// WebRequestAPI. Regression test for https://crbug.com/479841044.
-IN_PROC_BROWSER_TEST_F(ManifestV3WebRequestApiTestWithAlternativeAddListener,
+// Test that, when the `kWebRequestPersistFilteredEventsViaEventRouter` feature
+// flag is enabled, adding a listener right after an extension has been
+// unloaded, but before its renderer has been shut down, doesn't cause a CHECK
+// failure in WebRequestAPI. Regression test for https://crbug.com/479841044.
+IN_PROC_BROWSER_TEST_F(ManifestV3WebRequestApiTestWithEventRouterPersistence,
                        DontCrashOnExtensionUnload) {
   ASSERT_TRUE(StartEmbeddedTestServer());
   static constexpr char kManifest[] =
@@ -8510,35 +8514,17 @@
   base::RunLoop url_loader_factory_reset_runloop_;
 };
 
-class ManifestV3WebRequestApiTestWithSkipResetServiceWorkerURLLoaderFactories
-    : public ManifestV3WebRequestApiTest,
-      public testing::WithParamInterface<bool> {
- public:
-  ManifestV3WebRequestApiTestWithSkipResetServiceWorkerURLLoaderFactories() {
-    feature_list_.InitWithFeatureState(
-        extensions_features::kSkipResetServiceWorkerURLLoaderFactories,
-        GetParam());
-  }
-  ~ManifestV3WebRequestApiTestWithSkipResetServiceWorkerURLLoaderFactories()
-      override = default;
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
 // Tests that the call to `ResetURLLoaderFactories()` performed by WebRequestAPI
 // doesn't break the registration process of other extensions.
 // Regression test for https://crbug.com/394523691.
-IN_PROC_BROWSER_TEST_P(
-    ManifestV3WebRequestApiTestWithSkipResetServiceWorkerURLLoaderFactories,
-    ResetURLLoaderFactoryDoesntBreakRegistration) {
+IN_PROC_BROWSER_TEST_F(ManifestV3WebRequestApiTest,
+                       ResetURLLoaderFactoryDoesntBreakRegistration) {
   // Skip if the proxy is forced since factories will not be reset in that case.
   if (base::FeatureList::IsEnabled(
           extensions_features::kForceWebRequestProxyForTest)) {
     return;
   }
 
-  bool feature_enabled = GetParam();
   ASSERT_TRUE(StartEmbeddedTestServer());
 
   // A simple extension that sends a message and waits for a response in its
@@ -8574,9 +8560,8 @@
   ASSERT_TRUE(web_request_api);
 
   // Listen to "will_receive" message from the extension.
-  ExtensionTestMessageListener will_receive_listener(
-      "will_receive",
-      feature_enabled ? ReplyBehavior::kWillReply : ReplyBehavior::kWontReply);
+  ExtensionTestMessageListener will_receive_listener("will_receive",
+                                                     ReplyBehavior::kWillReply);
   // Listen to the completion of the registration storage.
   service_worker_test_utils::TestServiceWorkerContextObserver
       registration_observer(profile());
@@ -8611,35 +8596,20 @@
   // long and won't trigger the bug in all cases.
   web_request_api->ForceProxyForTesting();
 
-  if (feature_enabled) {
-    // SkipResetServiceWorkerURLLoaderFactories feature enabled: expect
-    // successful execution. Check that the worker is still running and
-    // functional.
-    registration_observer.WaitForWorkerStarted();
-    std::optional<WorkerId> worker_id = GetWorkerIdForExtension(extension_id);
-    EXPECT_TRUE(worker_id);
-    SCOPED_TRACE(
-        "Waiting for extension background to signal that it can send messages");
-    ASSERT_TRUE(will_receive_listener.WaitUntilSatisfied());
-    will_receive_listener.Reply("go");
-    url_loader_factories_reset_waiter.WaitForResetURLLoaderFactoriesCalled();
-    registration_observer.WaitForRegistrationStored();
-  } else {
-    // SkipResetServiceWorkerURLLoaderFactories feature disabled: expect worker
-    // registration to fail. We have observed that the registration can fail
-    // with either `kErrorStartWorkerFailed` or `kErrorNetwork` depending on
-    // when exactly it's interrupted.
-    auto status_code =
-        worker_failure_observer.WaitForWorkerRegistrationFailure();
-    EXPECT_NE(status_code, blink::ServiceWorkerStatusCode::kOk);
-  }
+  // SkipResetServiceWorkerURLLoaderFactories is now default behavior: expect
+  // successful execution. Check that the worker is still running and
+  // functional.
+  registration_observer.WaitForWorkerStarted();
+  std::optional<WorkerId> worker_id = GetWorkerIdForExtension(extension_id);
+  EXPECT_TRUE(worker_id);
+  SCOPED_TRACE(
+      "Waiting for extension background to signal that it can send messages");
+  ASSERT_TRUE(will_receive_listener.WaitUntilSatisfied());
+  will_receive_listener.Reply("go");
+  url_loader_factories_reset_waiter.WaitForResetURLLoaderFactoriesCalled();
+  registration_observer.WaitForRegistrationStored();
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    All,
-    ManifestV3WebRequestApiTestWithSkipResetServiceWorkerURLLoaderFactories,
-    testing::Bool());
-
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 
 // TODO(crbug.com/478208019): Test is flaky.
diff --git a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
index 5a97511..ecf0976 100644
--- a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
+++ b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
@@ -41,8 +41,9 @@
     : browser_context_(context) {
   // In unit tests, the SystemMonitor may not be created.
   base::SystemMonitor* system_monitor = base::SystemMonitor::Get();
-  if (system_monitor)
+  if (system_monitor) {
     system_monitor->AddDevicesChangedObserver(this);
+  }
 }
 
 WebrtcAudioPrivateEventService::~WebrtcAudioPrivateEventService() = default;
@@ -50,8 +51,9 @@
 void WebrtcAudioPrivateEventService::Shutdown() {
   // In unit tests, the SystemMonitor may not be created.
   base::SystemMonitor* system_monitor = base::SystemMonitor::Get();
-  if (system_monitor)
+  if (system_monitor) {
     system_monitor->RemoveDevicesChangedObserver(this);
+  }
 }
 
 // static
@@ -82,8 +84,9 @@
   using api::webrtc_audio_private::OnSinksChanged::kEventName;
 
   EventRouter* router = EventRouter::Get(browser_context_);
-  if (!router || !router->HasEventListener(kEventName))
+  if (!router || !router->HasEventListener(kEventName)) {
     return;
+  }
 
   for (const scoped_refptr<const extensions::Extension>& extension :
        ExtensionRegistry::Get(browser_context_)->enabled_extensions()) {
@@ -117,8 +120,9 @@
   // that transforms "default" to the empty string, and code in
   // GetActiveSink that ensures we return "default" if we get the
   // empty string as the current device ID.
-  if (media::AudioDeviceDescription::IsDefaultDevice(raw_id))
+  if (media::AudioDeviceDescription::IsDefaultDevice(raw_id)) {
     return media::AudioDeviceDescription::kDefaultDeviceId;
+  }
 
   return content::GetHMACForMediaDeviceID(extension_salt, GetExtensionOrigin(),
                                           raw_id);
@@ -158,8 +162,9 @@
 
 media::AudioSystem* WebrtcAudioPrivateFunction::GetAudioSystem() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!audio_system_)
+  if (!audio_system_) {
     audio_system_ = content::CreateAudioSystemForAudioService();
+  }
   return audio_system_.get();
 }
 
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
index 6e666561..79a87e4 100644
--- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
+++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
@@ -262,12 +262,14 @@
   std::string error;
   WebRtcLoggingController* webrtc_logging_controller =
       PrepareTask(params->request, params->security_origin, &callback, &error);
-  if (!webrtc_logging_controller)
+  if (!webrtc_logging_controller) {
     return RespondNow(Error(std::move(error)));
+  }
 
   std::unique_ptr<WebRtcLogMetaDataMap> meta_data(new WebRtcLogMetaDataMap());
-  for (const MetaDataEntry& entry : params->meta_data)
+  for (const MetaDataEntry& entry : params->meta_data) {
     (*meta_data)[entry.key] = entry.value;
+  }
 
   webrtc_logging_controller->SetMetaData(std::move(meta_data),
                                          std::move(callback));
@@ -282,8 +284,9 @@
   std::string error;
   WebRtcLoggingController* webrtc_logging_controller =
       PrepareTask(params->request, params->security_origin, &callback, &error);
-  if (!webrtc_logging_controller)
+  if (!webrtc_logging_controller) {
     return RespondNow(Error(std::move(error)));
+  }
 
   webrtc_logging_controller->StartLogging(std::move(callback));
   return RespondLater();
@@ -299,8 +302,9 @@
   WebRtcLoggingController* webrtc_logging_controller(
       LoggingControllerFromRequest(params->request, params->security_origin,
                                    &error));
-  if (!webrtc_logging_controller)
+  if (!webrtc_logging_controller) {
     return RespondNow(Error(std::move(error)));
+  }
 
   webrtc_logging_controller->set_upload_log_on_render_close(
       params->should_upload);
@@ -316,8 +320,9 @@
   std::string error;
   WebRtcLoggingController* webrtc_logging_controller =
       PrepareTask(params->request, params->security_origin, &callback, &error);
-  if (!webrtc_logging_controller)
+  if (!webrtc_logging_controller) {
     return RespondNow(Error(std::move(error)));
+  }
 
   webrtc_logging_controller->StopLogging(std::move(callback));
   return RespondLater();
@@ -331,8 +336,9 @@
   std::string error;
   WebRtcLoggingController* webrtc_logging_controller =
       PrepareTask(params->request, params->security_origin, &callback, &error);
-  if (!webrtc_logging_controller)
+  if (!webrtc_logging_controller) {
     return RespondNow(Error(std::move(error)));
+  }
 
   const std::string local_log_id(HashIdWithOrigin(params->security_origin,
                                                   params->log_id));
@@ -348,8 +354,9 @@
   std::string error;
   WebRtcLoggingController* logging_controller = LoggingControllerFromRequest(
       params->request, params->security_origin, &error);
-  if (!logging_controller)
+  if (!logging_controller) {
     return RespondNow(Error(std::move(error)));
+  }
 
   WebRtcLoggingController::UploadDoneCallback callback =
       base::BindOnce(&WebrtcLoggingPrivateUploadFunction::FireCallback, this);
@@ -366,8 +373,9 @@
   std::string error;
   WebRtcLoggingController* webrtc_logging_controller =
       PrepareTask(params->request, params->security_origin, &callback, &error);
-  if (!webrtc_logging_controller)
+  if (!webrtc_logging_controller) {
     return RespondNow(Error(std::move(error)));
+  }
 
   webrtc_logging_controller->DiscardLog(std::move(callback));
   return RespondLater();
diff --git a/chrome/browser/extensions/events_apitest.cc b/chrome/browser/extensions/events_apitest.cc
index 43ebf752..c266cce 100644
--- a/chrome/browser/extensions/events_apitest.cc
+++ b/chrome/browser/extensions/events_apitest.cc
@@ -1024,5 +1024,104 @@
       /*event_id=*/1));
 }
 
+// Tests that an unfiltered, top-level listener will receive events that are
+// essentially dispatched to a filtered event listener.
+IN_PROC_BROWSER_TEST_F(
+    EventsApiTest,
+    UnfilteredListenersReceiveEventsForRegisteredFilteredListeners) {
+  static constexpr char kManifest[] =
+      R"({
+           "name": "Test",
+           "manifest_version": 3,
+           "version": "0.1",
+           "background": {"service_worker": "background.js"},
+           "permissions": ["webNavigation"]
+         })";
+  // An extension background script that:
+  // * Registers a top-level, unfiltered event listener for all incoming
+  //   events.
+  // * Registers a non-top-level (async) event listener for a set of filters.
+  // * Unregisters the top-level listener when the async listener has been
+  //   registered.
+  // This simulates an extension that has a set of filters that it
+  // asynchronously loads, and uses those, but registers a listener
+  // synchronously as a workaround to receive the events.
+  // (This will be unnecessary -- but should still work -- once we have a better
+  // way for extensions to register listeners asynchronously at startup.)
+  static constexpr char kBackgroundJs[] =
+      R"(function unfilteredListener() {
+           chrome.test.sendMessage('received unfiltered');
+         }
+         chrome.webNavigation.onBeforeNavigate.addListener(unfilteredListener);
+         (async function() {
+           // Send an async message and wait for the reply. This simulates an
+           // asynchronous bootstrapping process in the extension.
+           await chrome.test.sendMessage('async');
+           chrome.webNavigation.onBeforeNavigate.addListener(
+               () => { },
+               {url: [{hostContains: 'example'}]});
+           chrome.webNavigation.onBeforeNavigate.removeListener(
+                unfilteredListener);
+           chrome.test.sendMessage('registered async');
+         })();)";
+
+  TestExtensionDir test_dir;
+  test_dir.WriteManifest(kManifest);
+  test_dir.WriteFile(FILE_PATH_LITERAL("background.js"), kBackgroundJs);
+
+  ExtensionTestMessageListener async_handler("async",
+                                             ReplyBehavior::kWillReply);
+  ExtensionTestMessageListener unfiltered_listener("received unfiltered");
+  ExtensionTestMessageListener registered_async("registered async");
+
+  // Load the extension and wait for the async handler to kick off.
+  const Extension* extension = LoadExtension(test_dir.UnpackedPath());
+  ASSERT_TRUE(extension);
+  ASSERT_TRUE(async_handler.WaitUntilSatisfied());
+  // Let the async registration continue, and wait for the event to register.
+  async_handler.Reply("");
+
+  ASSERT_TRUE(registered_async.WaitUntilSatisfied());
+
+  // Validate the registered listener. It should only be the filtered listener.
+  {
+    EventRouter* event_router = EventRouter::Get(profile());
+    std::vector<const EventListener*> registered_listeners;
+    const EventListenerMap::ListenerList& all_listeners =
+        event_router->listeners().GetEventListenersByName(
+            "webNavigation.onBeforeNavigate");
+    // Find registered listeners for the extension. There will be both active
+    // and lazy listeners; we only look at lazy listeners so we avoid the
+    // conceptual "duplicates".
+    for (const auto& listener : all_listeners) {
+      if (listener->extension_id() == extension->id() && listener->IsLazy()) {
+        registered_listeners.push_back(listener.get());
+      }
+    }
+    // There should only be one registered listener, which has a filter.
+    ASSERT_EQ(1u, registered_listeners.size());
+    ASSERT_TRUE(!!registered_listeners[0]->filter());
+  }
+
+  // Stop the service worker.
+  browsertest_util::StopServiceWorkerForExtensionGlobalScope(profile(),
+                                                             extension->id());
+
+  // Reset the async handler (so we can use it again). So far, we shouldn't
+  // have fired the unfiltered listener.
+  async_handler.Reset();
+  EXPECT_FALSE(unfiltered_listener.was_satisfied());
+
+  // Now, trigger the event (via a navigation to example.com).
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), embedded_test_server()->GetURL("example.com", "/empty.html")));
+
+  // The unfiltered listener should fire...
+  ASSERT_TRUE(unfiltered_listener.WaitUntilSatisfied());
+  // And we should reach the bootstrapping code again.
+  ASSERT_TRUE(async_handler.WaitUntilSatisfied());
+  async_handler.Reply("");
+}
+
 }  // namespace
 }  // namespace extensions
diff --git a/chrome/browser/extensions/extension_browser_window_helper.cc b/chrome/browser/extensions/extension_browser_window_helper.cc
index dacb899..e6d62492 100644
--- a/chrome/browser/extensions/extension_browser_window_helper.cc
+++ b/chrome/browser/extensions/extension_browser_window_helper.cc
@@ -32,6 +32,8 @@
 // is unloaded.
 bool ShouldCloseTabOnExtensionUnload(const Extension* extension,
                                      content::WebContents* web_contents) {
+  CHECK(web_contents);
+
   // Case 1: A "regular" extension page, e.g. chrome-extension://<id>/page.html.
   // Note: we check the tuple or precursor tuple in order to close any
   // windows with opaque origins that were opened by extensions, and may
@@ -68,6 +70,7 @@
 // |extension_id|.
 void UnmuteIfMutedByExtension(content::WebContents* contents,
                               const ExtensionId& extension_id) {
+  CHECK(contents);
   LastMuteMetadata::CreateForWebContents(contents);  // Ensures metadata exists.
   LastMuteMetadata* const metadata =
       LastMuteMetadata::FromWebContents(contents);
@@ -107,6 +110,13 @@
   // Iterate backwards as we may remove items while iterating.
   for (int i = tab_list->GetTabCount() - 1; i >= 0; --i) {
     content::WebContents* web_contents = tab_list->GetTab(i)->GetContents();
+#if BUILDFLAG(IS_ANDROID)
+    // TODO(http://crbug.com/453008083): Until kLoadAllTabsAtStartup and
+    // kWebContentsDiscard ship, `web_contents` may be null for some tabs.
+    if (!web_contents) {
+      continue;
+    }
+#endif  // BUILDFLAG(IS_ANDROID)
     if (ShouldCloseTabOnExtensionUnload(extension, web_contents)) {
       // Do not close the last tab if it belongs to the extension. Instead
       // replace it with the default NTP.
diff --git a/chrome/browser/extensions/service_worker_apitest.cc b/chrome/browser/extensions/service_worker_apitest.cc
index 21e5e87..c2d29aa 100644
--- a/chrome/browser/extensions/service_worker_apitest.cc
+++ b/chrome/browser/extensions/service_worker_apitest.cc
@@ -70,6 +70,8 @@
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/service_worker_test_helpers.h"
 #include "extensions/browser/api/web_request/extension_web_request_event_router.h"
+#include "extensions/browser/api/web_request/web_request_api_helpers.h"
+#include "extensions/browser/api/web_request/web_request_resource_type.h"
 #include "extensions/browser/browsertest_util.h"
 #include "extensions/browser/crx_installer.h"
 #include "extensions/browser/event_router.h"
@@ -2799,20 +2801,29 @@
 }
 
 class ServiceWorkerWebRequestPersistFilteredEventsTest
-    : public ServiceWorkerWebRequestEarlyListenerTest {
+    : public ServiceWorkerWebRequestEarlyListenerTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  ServiceWorkerWebRequestPersistFilteredEventsTest() {
+    scoped_feature_list_.InitWithFeatureState(
+        extensions_features::kWebRequestPersistFilteredEventsViaEventRouter,
+        GetParam());
+  }
+
  protected:
   WebRequestEventRouter* web_request_router() {
     return WebRequestEventRouter::Get(profile());
   }
 
  private:
+  base::test::ScopedFeatureList scoped_feature_list_;
   base::AutoReset<bool> disable_lazy_context_spinup_ =
       ExtensionRegistrar::DisableLazyContextSpinupForTest();
 };
 
 // Test that persisted webRequest filters are restored after browser restart.
 // Step 1: load the extension.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerWebRequestPersistFilteredEventsTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerWebRequestPersistFilteredEventsTest,
                        PRE_WebRequestAfterRestart) {
   base::FilePath extension_path = test_data_dir_.AppendASCII("service_worker")
                                       .AppendASCII("worker_based_background")
@@ -2831,7 +2842,7 @@
 }
 
 // Step 2: test that filters are restored post restart.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerWebRequestPersistFilteredEventsTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerWebRequestPersistFilteredEventsTest,
                        WebRequestAfterRestart) {
   // DO NOT wait for the listeners to be added by the service worker.
   // We rely on the persistence mechanism.
@@ -2844,6 +2855,20 @@
                     profile(), "webRequest.onBeforeRequest"));
   EXPECT_EQ(0u, web_request_router()->GetListenerCountForTesting(
                     profile(), "webRequest.onBeforeRequest"));
+
+  // Check that the listeners details have been properly restored.
+  int extra_info_spec = -1;
+  WebRequestEventRouter::RequestFilter* filter;
+  EXPECT_TRUE(web_request_router()->GetInactiveListenerDetailsForTesting(
+      profile(), extension->id(), "webRequest.onBeforeRequest", &filter,
+      &extra_info_spec));
+  EXPECT_FALSE(filter->urls.MatchesAllURLs());
+  EXPECT_TRUE(filter->urls.MatchesURL(GURL("http://127.0.0.1/empty.html")));
+  EXPECT_EQ(filter->types.size(), 1);
+  EXPECT_EQ(filter->types[0], WebRequestResourceType::MAIN_FRAME);
+  EXPECT_EQ(extra_info_spec,
+            extension_web_request_api_helpers::ExtraInfoSpec::EXTRA_HEADERS);
+
   // Navigate and expect the listener in the extension to be triggered.
   ResultCatcher catcher;
   catcher.RestrictToBrowserContext(profile());
@@ -2888,7 +2913,7 @@
 // Test that persisted webRequest filters are not restored after browser restart
 // if they were explicitly removed.
 // Step 1: load the extension that removes its listeners.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerWebRequestPersistFilteredEventsTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerWebRequestPersistFilteredEventsTest,
                        PRE_WebRequestAfterRestart_RemoveListener) {
   base::FilePath extension_path =
       test_data_dir_.AppendASCII("service_worker")
@@ -2913,7 +2938,7 @@
 }
 
 // Step 2: test that filters are NOT restored post restart.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerWebRequestPersistFilteredEventsTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerWebRequestPersistFilteredEventsTest,
                        WebRequestAfterRestart_RemoveListener) {
   // No service worker should be running yet.
   EXPECT_EQ(process_manager()->GetAllWorkersIdsForTesting().size(), 0u);
@@ -2925,6 +2950,12 @@
                     profile(), "webRequest.onBeforeRequest"));
 }
 
+// Instantiate test suite with the WebRequestPersistFilteredEventsViaEventRouter
+// feature flag enabled and disabled.
+INSTANTIATE_TEST_SUITE_P(All,
+                         ServiceWorkerWebRequestPersistFilteredEventsTest,
+                         testing::Bool());
+
 // Tests that chrome.browserAction.onClicked sees user gesture.
 IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest,
                        BrowserActionUserGesture) {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index c2e6c4c9..121b40e 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -2155,6 +2155,14 @@
     "owners": [ "cheickcisse@google.com", "bling-mony-pod@google.com" ],
     "expiry_milestone": 150
   },
+  {
+    "name": "default-browser-prompt-surfaces",
+    "owners": [
+      "top-chrome-desktop-ui@google.com",
+      "//chrome/browser/default_browser/OWNERS"
+    ],
+    "expiry_milestone": 150
+  },
   {  "name": "default-browser-video-in-settings",
      "owners": [ "gayane@google.com", "bling-flags@google.com" ],
      "expiry_milestone": 130
@@ -3908,11 +3916,6 @@
     "expiry_milestone": 108
   },
   {
-    "name": "enable-projector-server-side-speech-recognition",
-    "owners": ["yilkal@chromium.org", "cros-projector@google.com"],
-    "expiry_milestone": 115
-  },
-  {
     "name": "enable-projector-server-side-usm",
     "owners": [ "cros-projector@google.com" ],
     "expiry_milestone": 135
@@ -5227,6 +5230,11 @@
     "expiry_milestone": 150
   },
   {
+    "name": "glic-chrome-status-icon",
+    "owners": [ "iwells@chromium.org", "//chrome/browser/glic/OWNERS" ],
+    "expiry_milestone": 150
+  },
+  {
     "name": "glic-contextual-cue-bubble",
     "owners": [ "iwells@chromium.org" ],
     "expiry_milestone": 150
@@ -6698,11 +6706,6 @@
     "expiry_milestone": 130
   },
   {
-    "name": "nearby-mdns",
-    "owners": ["chromeos-cross-device-eng@google.com", "dclasson@google.com"],
-    "expiry_milestone": 130
-  },
-  {
     "name": "nearby-presence",
     "owners": [
       "chromeos-cross-device-eng@google.com",
@@ -6901,6 +6904,11 @@
     "expiry_milestone": 108
   },
   {
+    "name": "ntp-mvc-refactor",
+    "owners": ["hanxi@google.com", "yanlinghu@google.com", "clank-start@google.com"],
+    "expiry_milestone": 160
+  },
+  {
     "name": "ntp-next-features",
     "owners": [
       "jennserrano@google.com",
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 001a548..d6316e0 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -456,6 +456,11 @@
 inline constexpr char kDefaultBrowserFrameworkName[] =
     "Default Browser Framework";
 
+inline constexpr char kDefaultBrowserPromptSurfacesDescription[] =
+    "Enables using various default browser prompt surfaces.";
+inline constexpr char kDefaultBrowserPromptSurfacesName[] =
+    "Default Browser Prompt Surfaces";
+
 inline constexpr char kDefaultSearchEnginePrewarmName[] =
     "Default search engine prewarm";
 inline constexpr char kDefaultSearchEnginePrewarmDescription[] =
@@ -1362,6 +1367,9 @@
 inline constexpr char kGlicCaptureRegionDescription[] =
     "Enables Glic to capture a region of the screen.";
 inline constexpr char kGlicCaptureRegionName[] = "Glic Capture Region";
+inline constexpr char kGlicChromeStatusIconName[] = "Glic Chrome Status Icon";
+inline constexpr char kGlicChromeStatusIconDescription[] =
+    "Use the Chrome logo as glic OS status bar icon on Mac.";
 inline constexpr char kGlicDetachedName[] = "Glic detached-only mode";
 inline constexpr char kGlicDetachedDescription[] =
     "Detach only mode forces the Glic UI to always be floating";
@@ -5517,6 +5525,10 @@
     "Configure the dialog shown before requesting notification permission. "
     "Only works with builds targeting Android T.";
 
+inline constexpr char kNtpMvcRefactorName[] = "New Tab Page Refactor";
+inline constexpr char kNtpMvcRefactorDescription[] =
+    "Enables the refactor of the new tab page for MVC compliance.";
+
 inline constexpr char kOfflineAutoFetchName[] = "Offline Auto Fetch";
 inline constexpr char kOfflineAutoFetchDescription[] =
     "Enables auto fetch of content when Chrome is online";
@@ -7423,10 +7435,6 @@
 inline constexpr char kEnableNearbyBluetoothClassicAdvertisingDescription[] =
     "Enables Nearby advertising over Bluetooth Classic.";
 
-inline constexpr char kEnableNearbyMdnsName[] = "Nearby mDNS Discovery";
-inline constexpr char kEnableNearbyMdnsDescription[] =
-    "Enables Nearby discovery over mDNS.";
-
 inline constexpr char kNearbyPresenceName[] = "Nearby Presence";
 inline constexpr char kNearbyPresenceDescription[] =
     "Enables Nearby Presence for scanning and discovery of nearby devices.";
@@ -7470,11 +7478,6 @@
 inline constexpr char kProjectorAppDebugDescription[] =
     "Adds more informative error messages to the Projector app for debugging";
 
-inline constexpr char kProjectorServerSideSpeechRecognitionName[] =
-    "Enable server side speech recognition for Projector";
-inline constexpr char kProjectorServerSideSpeechRecognitionDescription[] =
-    "Adds server side speech recognition capability to Projector.";
-
 inline constexpr char kProjectorServerSideUsmName[] =
     "Enable USM for Projector server side speech recognition";
 inline constexpr char kProjectorServerSideUsmDescription[] =
diff --git a/chrome/browser/flags/BUILD.gn b/chrome/browser/flags/BUILD.gn
index b5ba05349..82ca9a2b 100644
--- a/chrome/browser/flags/BUILD.gn
+++ b/chrome/browser/flags/BUILD.gn
@@ -68,6 +68,7 @@
     "//chrome/browser/contextmenu",
     "//chrome/browser/glic/public:features",
     "//chrome/browser/notifications/chime/android",
+    "//chrome/browser/predictors",
     "//chrome/browser/task_manager/common",
     "//chrome/browser/ui:ui_features",
     "//chrome/common:chrome_features",
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index b39bb8bd..e8457e8 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -375,6 +375,7 @@
     &kNotificationPermissionVariant,
     &kNotificationTrampoline,
     &kNotificationTrampolineNoNewTask,
+    &kNtpMvcRefactor,
     &kOmahaMinSdkVersionAndroid,
     &kOnDemandBackgroundTabContextCapture,
     &kPCCTMinimumHeight,
@@ -707,6 +708,7 @@
 BASE_FEATURE(kNotificationPermissionVariant, base::FEATURE_DISABLED_BY_DEFAULT);
 BASE_FEATURE(kNotificationTrampoline, base::FEATURE_DISABLED_BY_DEFAULT);
 BASE_FEATURE(kNotificationTrampolineNoNewTask, base::FEATURE_DISABLED_BY_DEFAULT);
+BASE_FEATURE(kNtpMvcRefactor, base::FEATURE_DISABLED_BY_DEFAULT);
 BASE_FEATURE(kOmahaMinSdkVersionAndroid, base::FEATURE_DISABLED_BY_DEFAULT);
 BASE_FEATURE(kOnDemandBackgroundTabContextCapture, base::FEATURE_DISABLED_BY_DEFAULT);
 BASE_FEATURE(kPCCTMinimumHeight, base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h
index 59ce76b..0cd7271 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -205,6 +205,7 @@
 BASE_DECLARE_FEATURE(kNotificationPermissionVariant);
 BASE_DECLARE_FEATURE(kNotificationTrampoline);
 BASE_DECLARE_FEATURE(kNotificationTrampolineNoNewTask);
+BASE_DECLARE_FEATURE(kNtpMvcRefactor);
 BASE_DECLARE_FEATURE(kOmahaMinSdkVersionAndroid);
 BASE_DECLARE_FEATURE(kOnDemandBackgroundTabContextCapture);
 BASE_DECLARE_FEATURE(kOptimizeGeolocationHeaderGeneration);
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index 791d5ce..1c6d4d2 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -509,6 +509,7 @@
     public static final String NOTIFICATION_TRAMPOLINE = "NotificationTrampoline";
     public static final String NOTIFICATION_TRAMPOLINE_NO_NEW_TASK =
             "NotificationTrampolineNoNewTask";
+    public static final String NTP_MVC_REFACTOR = "NtpMvcRefactor";
     public static final String OMAHA_MIN_SDK_VERSION_ANDROID = "OmahaMinSdkVersionAndroid";
     public static final String OMNIBOX_AUTOFOCUS_ON_INCOGNITO_NTP =
             "OmniboxAutofocusOnIncognitoNtp";
@@ -993,6 +994,8 @@
                     NOTIFICATION_TRAMPOLINE_NO_NEW_TASK,
                     /* defaultValue= */ false,
                     /* defaultValueInTests= */ true);
+    public static final CachedFlag sNtpMvcRefactor =
+            newCachedFlag(NTP_MVC_REFACTOR, /* defaultValue= */ false);
     public static final CachedFlag sPCctMinimumHeight = newCachedFlag(PCCT_MINIMUM_HEIGHT, true);
     public static final CachedFlag sPaintPreviewDemo = newCachedFlag(PAINT_PREVIEW_DEMO, false);
     public static final CachedFlag sPersistAcrossReboots =
@@ -1224,6 +1227,7 @@
                     sNewTabPageCustomizationV2,
                     sNotificationTrampoline,
                     sNotificationTrampolineNoNewTask,
+                    sNtpMvcRefactor,
                     sPCctMinimumHeight,
                     sPaintPreviewDemo,
                     sPersistAcrossReboots,
diff --git a/chrome/browser/glic/BUILD.gn b/chrome/browser/glic/BUILD.gn
index c2619d1cd..f946cc3 100644
--- a/chrome/browser/glic/BUILD.gn
+++ b/chrome/browser/glic/BUILD.gn
@@ -428,6 +428,7 @@
       ":actor_types_for_migration",
       "//chrome/browser/context_sharing/tab_bottom_sheet/android:jni_headers",
       "//chrome/browser/glic/android",
+      "//ui/android",
     ]
   }
 
diff --git a/chrome/browser/glic/common/application_hotkey_delegate.cc b/chrome/browser/glic/common/application_hotkey_delegate.cc
index 2707e1f..47e6a489 100644
--- a/chrome/browser/glic/common/application_hotkey_delegate.cc
+++ b/chrome/browser/glic/common/application_hotkey_delegate.cc
@@ -22,11 +22,17 @@
 #include "components/prefs/pref_service.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/accelerators/accelerator_manager.h"
+#include "ui/base/base_window.h"
 
 #if !BUILDFLAG(IS_ANDROID)
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #endif
+#if BUILDFLAG(IS_ANDROID)
+#include "ui/android/accelerator_manager_android.h"
+#include "ui/android/view_android.h"
+#include "ui/android/window_android.h"
+#endif
 
 namespace glic {
 
@@ -58,7 +64,7 @@
 
   ~ApplicationScopedHotkeyRegistration() override {
     CHECK(target_);
-#if !BUILDFLAG(IS_ANDROID)  // NEEDS_ANDROID_IMPL: hotkey registration
+#if !BUILDFLAG(IS_ANDROID)
     ForEachCurrentBrowserWindowInterfaceOrderedByActivation(
         [this](BrowserWindowInterface* browser_window_interface) {
           if (auto* const browser_view = BrowserView::GetBrowserViewForBrowser(
@@ -68,6 +74,16 @@
           }
           return true;
         });
+#else
+    ForEachCurrentBrowserWindowInterfaceOrderedByActivation(
+        [this](BrowserWindowInterface* browser_window_interface) {
+          if (auto* window = browser_window_interface->GetWindow()) {
+            ui::AcceleratorManagerAndroid::FromWindow(
+                *window->GetNativeWindow())
+                ->UnregisterAccelerator(accelerator_, target_.get());
+          }
+          return true;
+        });
 #endif
   }
 
@@ -79,7 +95,7 @@
 
   void RegisterAccelerator(BrowserWindowInterface* browser_window_interface) {
     CHECK(target_);
-#if !BUILDFLAG(IS_ANDROID)  // NEEDS_ANDROID_IMPL: hotkey registration
+#if !BUILDFLAG(IS_ANDROID)
     if (auto* const browser_view =
             BrowserView::GetBrowserViewForBrowser(browser_window_interface)) {
       browser_view->GetFocusManager()->RegisterAccelerator(
@@ -87,6 +103,14 @@
           ui::AcceleratorManager::HandlerPriority::kNormalPriority,
           target_.get());
     }
+#else
+    if (auto* window = browser_window_interface->GetWindow()) {
+      ui::AcceleratorManagerAndroid::FromWindow(*window->GetNativeWindow())
+          ->RegisterAccelerator(
+              accelerator_,
+              ui::AcceleratorManager::HandlerPriority::kNormalPriority,
+              target_.get());
+    }
 #endif
   }
 
diff --git a/chrome/browser/glic/common/glic_panel_hotkey_delegate.cc b/chrome/browser/glic/common/glic_panel_hotkey_delegate.cc
index 1e417cd5..e8986f8 100644
--- a/chrome/browser/glic/common/glic_panel_hotkey_delegate.cc
+++ b/chrome/browser/glic/common/glic_panel_hotkey_delegate.cc
@@ -20,6 +20,8 @@
 
 #if !BUILDFLAG(IS_ANDROID)
 #include "chrome/browser/glic/widget/glic_view.h"
+#else
+#include "ui/android/window_android.h"
 #endif
 
 namespace glic {
@@ -34,6 +36,7 @@
 #endif
 };
 
+#if !BUILDFLAG(IS_ANDROID)
 // Implementation of ScopedHotkeyRegistration specifically for the Glic panel.
 // It registers and unregisters accelerators directly with the GlicView.
 class GlicPanelScopedHotkeyRegistration
@@ -58,6 +61,7 @@
   ui::Accelerator accelerator_;
   base::WeakPtr<views::View> glic_view_;
 };
+#endif
 
 }  // namespace
 
@@ -100,6 +104,8 @@
   }
 }
 
+#if !BUILDFLAG(IS_ANDROID)
+// Not supported on Android. Local hotkeys are handled in Java.
 std::unique_ptr<LocalHotkeyManager::ScopedHotkeyRegistration>
 GlicPanelHotkeyDelegate::CreateScopedHotkeyRegistration(
     ui::Accelerator accelerator,
@@ -108,6 +114,7 @@
   return std::make_unique<GlicPanelScopedHotkeyRegistration>(accelerator,
                                                              panel_->GetView());
 }
+#endif
 
 std::unique_ptr<LocalHotkeyManager> MakeGlicWindowHotkeyManager(
     base::WeakPtr<LocalHotkeyManager::Panel> panel) {
diff --git a/chrome/browser/glic/common/local_hotkey_manager.cc b/chrome/browser/glic/common/local_hotkey_manager.cc
index ec27f54..5ffe8d2 100644
--- a/chrome/browser/glic/common/local_hotkey_manager.cc
+++ b/chrome/browser/glic/common/local_hotkey_manager.cc
@@ -135,6 +135,7 @@
   auto pref_name_iter = kHotkeyToPrefMap.find(hotkey);
   CHECK(pref_name_iter != kHotkeyToPrefMap.end());
 
+  // NEEDS_ANDROID_IMPL: StringToAccelerator does not work on Android.
   const ui::Accelerator accelerator = ui::Command::StringToAccelerator(
       g_browser_process->local_state()->GetString(pref_name_iter->second));
 
diff --git a/chrome/browser/glic/common/local_hotkey_manager.h b/chrome/browser/glic/common/local_hotkey_manager.h
index 47f64b7..c1889d6 100644
--- a/chrome/browser/glic/common/local_hotkey_manager.h
+++ b/chrome/browser/glic/common/local_hotkey_manager.h
@@ -13,18 +13,15 @@
 #include "components/prefs/pref_change_registrar.h"
 #include "ui/base/accelerators/accelerator.h"
 
-#if !BUILDFLAG(IS_ANDROID)
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_list_observer.h"
-#endif
-
 namespace gfx {
 class Point;
 }
 
+#if !BUILDFLAG(IS_ANDROID)
 namespace views {
 class View;
 }
+#endif
 
 namespace glic {
 
@@ -57,7 +54,9 @@
     virtual void Close(const CloseOptions& options) = 0;
     virtual bool ActivateBrowser() = 0;
     virtual void ShowTitleBarContextMenuAt(gfx::Point event_loc) = 0;
+#if !BUILDFLAG(IS_ANDROID)
     virtual base::WeakPtr<views::View> GetView() = 0;
+#endif
   };
 
   constexpr static const char* HotkeyToString(Hotkey hotkey) {
diff --git a/chrome/browser/glic/fre/BUILD.gn b/chrome/browser/glic/fre/BUILD.gn
index f207204..5bef281 100644
--- a/chrome/browser/glic/fre/BUILD.gn
+++ b/chrome/browser/glic/fre/BUILD.gn
@@ -22,6 +22,7 @@
     "//chrome/browser/background/glic",
     "//chrome/browser/glic",
     "//chrome/browser/glic/shared",
+    "//chrome/browser/predictors",
     "//chrome/browser/resources/glic:resources",
     "//chrome/browser/resources/glic/fre:resources_grit",
     "//components/language/core/common",
diff --git a/chrome/browser/glic/glic_metrics.h b/chrome/browser/glic/glic_metrics.h
index c2b148f..0b00fb4c 100644
--- a/chrome/browser/glic/glic_metrics.h
+++ b/chrome/browser/glic/glic_metrics.h
@@ -209,7 +209,11 @@
   kNavigationCaptureAttachedAudio = 74,
   kNavigationCaptureDetachedText = 75,
   kNavigationCaptureDetachedAudio = 76,
-  kMaxValue = kNavigationCaptureDetachedAudio,
+  kAutoOpenedForPdfAttachedText = 77,
+  kAutoOpenedForPdfAttachedAudio = 78,
+  kAutoOpenedForPdfDetachedText = 79,
+  kAutoOpenedForPdfDetachedAudio = 80,
+  kMaxValue = kAutoOpenedForPdfDetachedAudio,
 };
 // LINT.ThenChange(//tools/metrics/histograms/metadata/glic/enums.xml:GlicResponseSegmentation)
 
diff --git a/chrome/browser/glic/glic_zero_state_suggestions_manager.cc b/chrome/browser/glic/glic_zero_state_suggestions_manager.cc
index e94aeea..1502049 100644
--- a/chrome/browser/glic/glic_zero_state_suggestions_manager.cc
+++ b/chrome/browser/glic/glic_zero_state_suggestions_manager.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/contextual_cueing/contextual_cueing_service.h"
 #include "chrome/browser/glic/host/host.h"
 #include "chrome/browser/glic/public/context/glic_sharing_manager.h"
+#include "chrome/browser/glic/public/features.h"
 #include "chrome/browser/glic/public/glic_enabling.h"
 #include "chrome/browser/glic/suggestions/caching_zero_state_suggestions_manager.h"
 #include "content/public/browser/navigation_controller.h"
@@ -25,10 +26,13 @@
 namespace glic {
 namespace {
 
-mojom::ZeroStateSuggestionsV2Ptr MakeEmptySuggestionsPtr() {
+mojom::ZeroStateSuggestionsV2Ptr MakeEmptySuggestionsPtr(
+    std::optional<mojom::InvocationSource> invocation_source) {
   auto suggestions_ptr = mojom::ZeroStateSuggestionsV2::New();
   std::vector<mojom::SuggestionContentPtr> empty_suggestions;
   suggestions_ptr->suggestions = std::move(empty_suggestions);
+  suggestions_ptr->invocation_source =
+      invocation_source.value_or(mojom::InvocationSource::kUnsupported);
   return suggestions_ptr;
 }
 
@@ -46,8 +50,9 @@
   return {};
 }
 
-mojom::ZeroStateSuggestionsV2Ptr MakePendingSuggestionsPtr() {
-  auto pending_suggestions = MakeEmptySuggestionsPtr();
+mojom::ZeroStateSuggestionsV2Ptr MakePendingSuggestionsPtr(
+    std::optional<mojom::InvocationSource> invocation_source) {
+  auto pending_suggestions = MakeEmptySuggestionsPtr(invocation_source);
   pending_suggestions->is_pending = true;
   return pending_suggestions;
 }
@@ -121,7 +126,7 @@
   if (contextual_cueing_service_ && active_web_contents) {
     // Notify host that suggestions are pending.
     host().NotifyZeroStateSuggestion(
-        MakePendingSuggestionsPtr(),
+        MakePendingSuggestionsPtr(host().invocation_source()),
         mojom::ZeroStateSuggestionsOptions(is_first_run, supported_tools));
 
     if (caching_zero_state_manager_) {
@@ -224,7 +229,7 @@
     if (suggestions_pending) {
       // Notify host that suggestions are pending.
       host().NotifyZeroStateSuggestion(
-          MakePendingSuggestionsPtr(),
+          MakePendingSuggestionsPtr(host().invocation_source()),
           mojom::ZeroStateSuggestionsOptions(is_first_run, supported_tools));
     }
   }
@@ -261,9 +266,12 @@
         callback) {
   // Subscribe to changes in sharing.
   if (is_notifying) {
-    // Skip ZSS generation for unconsented users.
-    if (!GlicEnabling::HasConsentedForProfile(host().profile())) {
-      std::move(callback).Run(MakeEmptySuggestionsPtr());
+    // Skip ZSS generation for unconsented users or if the panel was auto-opened
+    // for a PDF.
+    if (!GlicEnabling::HasConsentedForProfile(host().profile()) ||
+        WasAutoOpenedForPdf()) {
+      std::move(callback).Run(
+          MakeEmptySuggestionsPtr(host().invocation_source()));
       return;
     }
     // If there were previous subscriptions they will be unsubscribed when the
@@ -292,7 +300,8 @@
                !pinned_tabs.empty()) {
       FilterTabs(pinned_tabs);
       if (pinned_tabs.empty()) {
-        std::move(callback).Run(MakeEmptySuggestionsPtr());
+        std::move(callback).Run(
+            MakeEmptySuggestionsPtr(host().invocation_source()));
         return;
       } else if (caching_zero_state_manager_) {
         caching_zero_state_manager_
@@ -389,6 +398,12 @@
   current_zero_state_suggestions_pinned_tab_data_change_subscription_ = {};
 }
 
+bool GlicZeroStateSuggestionsManager::WasAutoOpenedForPdf() {
+  return base::FeatureList::IsEnabled(features::kAutoOpenGlicForPdf) &&
+         host().invocation_source() ==
+             mojom::InvocationSource::kAutoOpenedForPdf;
+}
+
 base::WeakPtr<GlicZeroStateSuggestionsManager>
 GlicZeroStateSuggestionsManager::GetWeakPtr() {
   return weak_ptr_factory_.GetWeakPtr();
diff --git a/chrome/browser/glic/glic_zero_state_suggestions_manager.h b/chrome/browser/glic/glic_zero_state_suggestions_manager.h
index 2bbde1cd..72fae7f 100644
--- a/chrome/browser/glic/glic_zero_state_suggestions_manager.h
+++ b/chrome/browser/glic/glic_zero_state_suggestions_manager.h
@@ -63,6 +63,7 @@
   void Reset();
 
  private:
+  bool WasAutoOpenedForPdf();
   void FilterTabs(std::vector<content::WebContents*>& tabs);
 
   // A helper function to route GetZeroStateSuggestionsForFocusedTabCallback
diff --git a/chrome/browser/glic/host/glic.mojom b/chrome/browser/glic/host/glic.mojom
index 833ac487..1c27063 100644
--- a/chrome/browser/glic/host/glic.mojom
+++ b/chrome/browser/glic/host/glic.mojom
@@ -705,6 +705,8 @@
   // Whether there is a current outstanding request to generate suggestions for
   // the current tab context.
   bool is_pending;
+  // The host's invocation source.
+  InvocationSource invocation_source;
 };
 
 // The options associated with the current zero state suggestions.
@@ -1356,6 +1358,8 @@
   [MinVersion=9] kPdfSummarizeButton = 17,
   // From a navigation capture.
   [MinVersion=10] kNavigationCapture = 18,
+  // Automatically opened for a PDF.
+  [MinVersion=11] kAutoOpenedForPdf = 19,
 };
 
 // LINT.ThenChange(//tools/metrics/histograms/metadata/glic/enums.xml:GlicInvocationSource, //chrome/browser/glic/glic_metrics.h:ResponseSegmentation)
@@ -1872,4 +1876,6 @@
   kTrustFirstOnboardingArm2 = 5,
   // Glic host supports sharing additional image context.
   kShareAdditionalImageContext = 6,
+  // Enables the PDF Zero State Web UI.
+  kPdfZeroState = 7,
 };
diff --git a/chrome/browser/glic/host/glic_api_browsertest.cc b/chrome/browser/glic/host/glic_api_browsertest.cc
index 4c94e6e..7322275 100644
--- a/chrome/browser/glic/host/glic_api_browsertest.cc
+++ b/chrome/browser/glic/host/glic_api_browsertest.cc
@@ -56,6 +56,7 @@
 #include "chrome/browser/glic/host/glic_web_contents_warming_pool.h"
 #include "chrome/browser/glic/host/host.h"
 #include "chrome/browser/glic/host/webui_contents_container.h"
+#include "chrome/browser/glic/public/features.h"
 #include "chrome/browser/glic/public/glic_keyed_service.h"
 #include "chrome/browser/glic/public/glic_keyed_service_factory.h"
 #include "chrome/browser/glic/public/glic_side_panel_coordinator.h"
@@ -202,6 +203,7 @@
   bool enable_scroll_to_pdf = false;
   bool trust_first_onboarding_arm1 = false;
   bool trust_first_onboarding_arm2 = false;
+  bool auto_open_pdf = false;
 };
 
 class WithTestParams : public testing::WithParamInterface<TestParams> {
@@ -229,6 +231,9 @@
     if (info.param.trust_first_onboarding_arm2) {
       result.push_back("TrustFirstOnboardingArm2");
     }
+    if (info.param.auto_open_pdf) {
+      result.push_back("AutoOpenPdf");
+    }
     if (result.empty()) {
       return "Default";
     }
@@ -3613,6 +3618,10 @@
       disabled_features.push_back(features::kGlicTrustFirstOnboarding);
     }
 
+    if (GetParam().auto_open_pdf) {
+      enabled_features.push_back({features::kAutoOpenGlicForPdf, {}});
+    }
+
     scoped_feature_list_.InitWithFeaturesAndParameters(enabled_features,
                                                        disabled_features);
   }
@@ -3639,6 +3648,10 @@
     expected_capabilities.Append(
         std::to_underlying(mojom::HostCapability::kTrustFirstOnboardingArm2));
   }
+  if (GetParam().auto_open_pdf) {
+    expected_capabilities.Append(
+        std::to_underlying(mojom::HostCapability::kPdfZeroState));
+  }
   ExecuteJsTest({.params = base::Value(std::move(expected_capabilities))});
 }
 
@@ -4008,7 +4021,8 @@
     testing::Values(TestParams{},
                     TestParams{.enable_scroll_to_pdf = true},
                     TestParams{.trust_first_onboarding_arm1 = true},
-                    TestParams{.trust_first_onboarding_arm2 = true}),
+                    TestParams{.trust_first_onboarding_arm2 = true},
+                    TestParams{.auto_open_pdf = true}),
     &WithTestParams::PrintTestVariant);
 
 auto DefaultTestParamSet() {
diff --git a/chrome/browser/glic/host/glic_page_handler.cc b/chrome/browser/glic/host/glic_page_handler.cc
index a3133d1b..261eda3 100644
--- a/chrome/browser/glic/host/glic_page_handler.cc
+++ b/chrome/browser/glic/host/glic_page_handler.cc
@@ -54,6 +54,7 @@
 #include "chrome/browser/glic/host/page_metadata_manager.h"
 #include "chrome/browser/glic/media/glic_media_link_helper.h"
 #include "chrome/browser/glic/public/context/glic_sharing_manager.h"
+#include "chrome/browser/glic/public/features.h"
 #include "chrome/browser/glic/public/glic_enabling.h"
 #include "chrome/browser/glic/public/glic_keyed_service.h"
 #include "chrome/browser/glic/public/glic_keyed_service_factory.h"
@@ -988,6 +989,10 @@
       state->host_capabilities.push_back(mojom::HostCapability::kMultiInstance);
     }
 
+    if (base::FeatureList::IsEnabled(features::kAutoOpenGlicForPdf)) {
+      state->host_capabilities.push_back(mojom::HostCapability::kPdfZeroState);
+    }
+
     const mojom::InvocationSource invocation_source =
         host().invocation_source().value_or(
             mojom::InvocationSource::kUnsupported);
@@ -1035,6 +1040,7 @@
         base::FeatureList::IsEnabled(
             features::kGlicOpenPasswordManagerSettingsPageApi);
     state->enable_trust_first_onboarding =
+        !should_bypass_fre_ui &&
         GlicEnabling::IsTrustFirstOnboardingEnabledForProfile(profile_);
     state->onboarding_completed =
         GlicEnabling::HasConsentedForProfile(profile_);
diff --git a/chrome/browser/glic/host/glic_region_capture_controller.cc b/chrome/browser/glic/host/glic_region_capture_controller.cc
index 7e32c28..1dfda13 100644
--- a/chrome/browser/glic/host/glic_region_capture_controller.cc
+++ b/chrome/browser/glic/host/glic_region_capture_controller.cc
@@ -7,7 +7,7 @@
 #include "base/feature_list.h"
 #include "chrome/browser/glic/host/context/glic_tab_data.h"
 #include "chrome/browser/glic/host/glic.mojom.h"
-#include "chrome/browser/glic/selection/selection_overlay_features.h"
+#include "chrome/common/chrome_features.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 
diff --git a/chrome/browser/glic/public/features.cc b/chrome/browser/glic/public/features.cc
index a6ca784..2875034c 100644
--- a/chrome/browser/glic/public/features.cc
+++ b/chrome/browser/glic/public/features.cc
@@ -10,6 +10,8 @@
 
 BASE_FEATURE(kGlicTabRestoration, base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kGlicChromeStatusIcon, base::FEATURE_DISABLED_BY_DEFAULT);
+
 BASE_FEATURE(kGlicOrphanedReattachment, base::FEATURE_ENABLED_BY_DEFAULT);
 
 #if BUILDFLAG(IS_ANDROID)
@@ -20,7 +22,4 @@
 
 BASE_FEATURE(kAutoOpenGlicForPdf, base::FEATURE_DISABLED_BY_DEFAULT);
 
-const base::FeatureParam<std::string> kAutoOpenGlicForPdfArm{
-    &kAutoOpenGlicForPdf, "arm", "standardZS"};
-
 }  // namespace features
diff --git a/chrome/browser/glic/public/features.h b/chrome/browser/glic/public/features.h
index c0bdae7..54ae94c 100644
--- a/chrome/browser/glic/public/features.h
+++ b/chrome/browser/glic/public/features.h
@@ -12,11 +12,11 @@
 
 BASE_DECLARE_FEATURE(kGlicTabRestoration);
 BASE_DECLARE_FEATURE(kGlicDaisyChainViaCoordinator);
+BASE_DECLARE_FEATURE(kGlicChromeStatusIcon);
 
 BASE_DECLARE_FEATURE(kGlicOrphanedReattachment);
 
 BASE_DECLARE_FEATURE(kAutoOpenGlicForPdf);
-extern const base::FeatureParam<std::string> kAutoOpenGlicForPdfArm;
 
 }  // namespace features
 
diff --git a/chrome/browser/glic/public/glic_keyed_service.cc b/chrome/browser/glic/public/glic_keyed_service.cc
index 6121a980..b938928e 100644
--- a/chrome/browser/glic/public/glic_keyed_service.cc
+++ b/chrome/browser/glic/public/glic_keyed_service.cc
@@ -28,6 +28,7 @@
 #include "chrome/browser/contextual_cueing/contextual_cueing_service_factory.h"
 #include "chrome/browser/glic/actor/glic_actor_policy_checker.h"
 #include "chrome/browser/glic/actor/glic_actor_task_manager.h"
+#include "chrome/browser/glic/common/application_hotkey_delegate.h"
 #include "chrome/browser/glic/common/future_browser_features.h"
 #include "chrome/browser/glic/fre/glic_fre_controller.h"
 #include "chrome/browser/glic/glic_enums.h"
diff --git a/chrome/browser/glic/public/glic_keyed_service.h b/chrome/browser/glic/public/glic_keyed_service.h
index 9c72960..2f2112d 100644
--- a/chrome/browser/glic/public/glic_keyed_service.h
+++ b/chrome/browser/glic/public/glic_keyed_service.h
@@ -15,6 +15,7 @@
 #include "base/memory/memory_pressure_listener.h"
 #include "base/memory/raw_ptr.h"
 #include "build/build_config.h"
+#include "chrome/browser/glic/common/local_hotkey_manager.h"
 #include "chrome/browser/glic/glic_metrics.h"
 #include "chrome/browser/glic/glic_zero_state_suggestions_manager.h"
 #include "chrome/browser/glic/host/context/glic_sharing_manager_provider.h"
diff --git a/chrome/browser/glic/selection/BUILD.gn b/chrome/browser/glic/selection/BUILD.gn
index 2499ebf7..fa65a714 100644
--- a/chrome/browser/glic/selection/BUILD.gn
+++ b/chrome/browser/glic/selection/BUILD.gn
@@ -11,8 +11,8 @@
   sources = [
     "selection_overlay_controller.cc",
     "selection_overlay_controller.h",
-    "selection_overlay_features.cc",
-    "selection_overlay_features.h",
+    "selection_overlay_untrusted_ui.cc",
+    "selection_overlay_untrusted_ui.h",
   ]
 
   deps = [
@@ -23,6 +23,7 @@
     "//chrome/browser/ui:browser_element_identifiers",
     "//chrome/browser/ui/lens",
     "//chrome/browser/ui/webui:webui_util",
+    "//chrome/browser/ui/webui/top_chrome",
     "//mojo/public/mojom/base",
   ]
 }
diff --git a/chrome/browser/glic/selection/selection_overlay.mojom b/chrome/browser/glic/selection/selection_overlay.mojom
index dc4cf899..335a127 100644
--- a/chrome/browser/glic/selection/selection_overlay.mojom
+++ b/chrome/browser/glic/selection/selection_overlay.mojom
@@ -24,8 +24,16 @@
   kBackgroundClick = 1,
 };
 
+// `chrome-untrusted://glic/selection-overlay/` WebUI calls this interface to
+// setup the mojo channel.
+interface SelectionOverlayPageHandlerFactory {
+  // Called when the WebUI page is initialized. Sets up the mojom channel.
+  CreatePageHandler(pending_receiver<SelectionOverlayPageHandler> handler,
+                    pending_remote<SelectionOverlayPage> page);
+};
+
 // C++ handler that receives requests from the
-// `chrome-untrusted://glic-selection-overlay/` WebUI.
+// `chrome-untrusted://glic/selection-overlay/` WebUI.
 interface SelectionOverlayPageHandler {
   // The WebUI informs the browser to dismiss the selection overlay with a
   // specific reason.
@@ -39,7 +47,7 @@
   DeleteRegion(mojo_base.mojom.UnguessableToken id);
 };
 
-// `chrome-untrusted://glic-selection-overlay/` WebUI page handler that receives
+// `chrome-untrusted://glic/selection-overlay/` WebUI page handler that receives
 // requests from the browser.
 interface SelectionOverlayPage {
   // Pass the screenshot from the browser to the WebUI. `screenshot` is captured
diff --git a/chrome/browser/glic/selection/selection_overlay_controller.cc b/chrome/browser/glic/selection/selection_overlay_controller.cc
index 90cff04..8ff7cf38 100644
--- a/chrome/browser/glic/selection/selection_overlay_controller.cc
+++ b/chrome/browser/glic/selection/selection_overlay_controller.cc
@@ -8,11 +8,12 @@
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/webui/webui_embedding_context.h"
 #include "chrome/common/webui_url_constants.h"
-#include "chrome/grit/branded_strings.h"
+#include "chrome/grit/generated_resources.h"
 #include "components/viz/common/frame_sinks/copy_output_result.h"
 #include "content/public/browser/render_view_host.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/effects/SkDashPathEffect.h"
 #include "ui/gfx/codec/jpeg_codec.h"
 #include "ui/gfx/geometry/skia_conversions.h"
 
@@ -99,7 +100,7 @@
   // We can only continue once both the WebUI is bound and the initialization
   // data is processed and ready. If either of those conditions aren't met, we
   // exit early and wait for the other condition to call this method again.
-  if (!screenshot_available_) {
+  if (!page_ || !screenshot_available_) {
     return;
   }
 
@@ -145,20 +146,17 @@
 }
 
 GURL SelectionOverlayController::GetInitialURL() {
-  // TODO(b:479179977): Switch to glic selection overlay.
-  return GURL(chrome::kChromeUILensOverlayUntrustedURL);
+  return GURL(chrome::kChromeUIGlicSelectionOverlayURL);
 }
 
 void SelectionOverlayController::NotifyIsOverlayShowing(bool is_showing) {}
 
 int SelectionOverlayController::GetToolResourceId() {
-  // TODO(b:479179977): Switch to glic selection overlay.
-  return IDS_LENS_OVERLAY_RENDERER_LABEL;
+  return IDS_GLIC_SELECTION_OVERLAY_RENDERER_LABEL;
 }
 
 ui::ElementIdentifier SelectionOverlayController::GetViewContainerId() {
-  // TODO(b:479179977): Switch to glic selection overlay.
-  return kLensOverlayViewElementId;
+  return kGlicSelectionOverlayViewElementId;
 }
 
 SidePanelEntry::PanelType SelectionOverlayController::GetSidePanelType() {
@@ -183,6 +181,12 @@
 
 void SelectionOverlayController::NotifyTabWillEnterBackground() {}
 
+bool SelectionOverlayController::IsOverlayViewShared() const {
+  // Glic's selection overlay's WebView is attached to the ContentsContainerView
+  // which cannot be shared across multiple tabs.
+  return false;
+}
+
 void SelectionOverlayController::DismissOverlay(
     selection::DismissOverlayReason reason) {
   CloseUI();
@@ -233,7 +237,7 @@
   SkCanvas canvas(deep_copy_bitmap);
   canvas.drawImage(initial_screenshot_.asImage(), 0, 0);
   SkPaint paint;
-  paint.setColor(SK_ColorMAGENTA);
+  const SkScalar intervals[] = {5.0f, 5.0f};
   paint.setStyle(SkPaint::kStroke_Style);
   paint.setStrokeWidth(2.0f);
 
@@ -245,6 +249,11 @@
     SkRect rect_on_canvas = gfx::RectFToSkRect(region->region);
     if (!rect_on_canvas.isEmpty() &&
         initial_screenshot_.bounds().contains(rect_on_canvas)) {
+      paint.setColor(SK_ColorMAGENTA);
+      paint.setPathEffect(SkDashPathEffect::Make(intervals, 0.0f));
+      canvas.drawRect(rect_on_canvas, paint);
+      paint.setPathEffect(SkDashPathEffect::Make(intervals, -5.0f));
+      paint.setColor(SK_ColorCYAN);
       canvas.drawRect(rect_on_canvas, paint);
     } else {
       // TODO(http://b/485358530): Record proper histograms for the error case.
diff --git a/chrome/browser/glic/selection/selection_overlay_controller.h b/chrome/browser/glic/selection/selection_overlay_controller.h
index 3cacb5c..f0781fb 100644
--- a/chrome/browser/glic/selection/selection_overlay_controller.h
+++ b/chrome/browser/glic/selection/selection_overlay_controller.h
@@ -73,6 +73,7 @@
   void NotifyPageNavigated() override;
   void NotifyTabForegrounded() override;
   void NotifyTabWillEnterBackground() override;
+  bool IsOverlayViewShared() const override;
 
   // `selection::SelectionOverlayPageHandler`:
   void DismissOverlay(selection::DismissOverlayReason reason) override;
diff --git a/chrome/browser/glic/selection/selection_overlay_features.cc b/chrome/browser/glic/selection/selection_overlay_features.cc
deleted file mode 100644
index 0f6c3ff..0000000
--- a/chrome/browser/glic/selection/selection_overlay_features.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2026 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/glic/selection/selection_overlay_features.h"
-
-#include "base/feature_list.h"
-
-namespace glic::features {
-
-BASE_FEATURE(kGlicRegionSelectionNew, base::FEATURE_DISABLED_BY_DEFAULT);
-
-}  // namespace glic::features
diff --git a/chrome/browser/glic/selection/selection_overlay_features.h b/chrome/browser/glic/selection/selection_overlay_features.h
deleted file mode 100644
index b7b0bc9..0000000
--- a/chrome/browser/glic/selection/selection_overlay_features.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2026 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_GLIC_SELECTION_SELECTION_OVERLAY_FEATURES_H_
-#define CHROME_BROWSER_GLIC_SELECTION_SELECTION_OVERLAY_FEATURES_H_
-
-#include "base/feature_list.h"
-
-namespace glic::features {
-
-// Enable new new region selection code path based on Lens overlay controller.
-BASE_DECLARE_FEATURE(kGlicRegionSelectionNew);
-
-}  // namespace glic::features
-
-#endif  // CHROME_BROWSER_GLIC_SELECTION_SELECTION_OVERLAY_FEATURES_H_
diff --git a/chrome/browser/glic/selection/selection_overlay_untrusted_ui.cc b/chrome/browser/glic/selection/selection_overlay_untrusted_ui.cc
new file mode 100644
index 0000000..af0a25b8e
--- /dev/null
+++ b/chrome/browser/glic/selection/selection_overlay_untrusted_ui.cc
@@ -0,0 +1,64 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/glic/selection/selection_overlay_untrusted_ui.h"
+
+#include "base/feature_list.h"
+#include "chrome/browser/glic/public/glic_enabling.h"
+#include "chrome/browser/glic/selection/selection_overlay_controller.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/common/webui_url_constants.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "ui/webui/webui_util.h"
+
+namespace glic {
+
+bool SelectionOverlayUntrustedUIConfig::IsWebUIEnabled(
+    content::BrowserContext* browser_context) {
+  return GlicEnabling::IsProfileEligible(
+             Profile::FromBrowserContext(browser_context)) &&
+         base::FeatureList::IsEnabled(features::kGlicRegionSelectionNew);
+}
+
+SelectionOverlayUntrustedUI::SelectionOverlayUntrustedUI(content::WebUI* web_ui)
+    : UntrustedTopChromeWebUIController(web_ui) {
+  // Set up the chrome-untrusted://glic/selection-overlay source.
+  content::WebUIDataSource* html_source =
+      content::WebUIDataSource::CreateAndAdd(
+          web_ui->GetWebContents()->GetBrowserContext(),
+          chrome::kChromeUIGlicUntrustedURL);
+  CHECK(html_source);
+  // TODO(b/479179977): Add resources.
+}
+
+SelectionOverlayUntrustedUI::~SelectionOverlayUntrustedUI() = default;
+
+void SelectionOverlayUntrustedUI::BindInterface(
+    mojo::PendingReceiver<selection::SelectionOverlayPageHandlerFactory>
+        receiver) {
+  selection_page_factory_receiver_.reset();
+  selection_page_factory_receiver_.Bind(std::move(receiver));
+}
+
+SelectionOverlayController&
+SelectionOverlayUntrustedUI::GetSelectionOverlayController() {
+  SelectionOverlayController* controller =
+      SelectionOverlayController::FromOverlayWebContents(
+          web_ui()->GetWebContents());
+  return *controller;
+}
+
+void SelectionOverlayUntrustedUI::CreatePageHandler(
+    mojo::PendingReceiver<selection::SelectionOverlayPageHandler> receiver,
+    mojo::PendingRemote<selection::SelectionOverlayPage> page) {
+  SelectionOverlayController& controller = GetSelectionOverlayController();
+  controller.BindOverlay(std::move(receiver), std::move(page));
+}
+
+WEB_UI_CONTROLLER_TYPE_IMPL(SelectionOverlayUntrustedUI)
+
+}  // namespace glic
diff --git a/chrome/browser/glic/selection/selection_overlay_untrusted_ui.h b/chrome/browser/glic/selection/selection_overlay_untrusted_ui.h
new file mode 100644
index 0000000..c99e68a
--- /dev/null
+++ b/chrome/browser/glic/selection/selection_overlay_untrusted_ui.h
@@ -0,0 +1,71 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_GLIC_SELECTION_SELECTION_OVERLAY_UNTRUSTED_UI_H_
+#define CHROME_BROWSER_GLIC_SELECTION_SELECTION_OVERLAY_UNTRUSTED_UI_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/glic/selection/selection_overlay.mojom.h"
+#include "chrome/browser/ui/webui/top_chrome/top_chrome_webui_config.h"
+#include "chrome/browser/ui/webui/top_chrome/untrusted_top_chrome_web_ui_controller.h"
+#include "chrome/common/webui_url_constants.h"
+#include "content/public/common/url_constants.h"
+
+namespace glic {
+
+class SelectionOverlayController;
+class SelectionOverlayUntrustedUI;
+
+class SelectionOverlayUntrustedUIConfig
+    : public DefaultTopChromeWebUIConfig<SelectionOverlayUntrustedUI> {
+ public:
+  SelectionOverlayUntrustedUIConfig()
+      : DefaultTopChromeWebUIConfig(content::kChromeUIUntrustedScheme,
+                                    chrome::kChromeUIGlicUntrustedHost) {}
+
+  // `DefaultTopChromeWebUIConfig`:
+  bool IsWebUIEnabled(content::BrowserContext* browser_context) override;
+};
+
+// WebUI controller for the chrome-untrusted://glic/selection-overlay page.
+class SelectionOverlayUntrustedUI
+    : public UntrustedTopChromeWebUIController,
+      public selection::SelectionOverlayPageHandlerFactory {
+ public:
+  explicit SelectionOverlayUntrustedUI(content::WebUI* web_ui);
+
+  SelectionOverlayUntrustedUI(const SelectionOverlayUntrustedUI&) = delete;
+  SelectionOverlayUntrustedUI& operator=(const SelectionOverlayUntrustedUI&) =
+      delete;
+  ~SelectionOverlayUntrustedUI() override;
+
+  // Instantiates the implementor of the PageHandlerFactory mojo interface
+  // passing the pending receiver that will be internally bound.
+  void BindInterface(
+      mojo::PendingReceiver<selection::SelectionOverlayPageHandlerFactory>
+          receiver);
+
+  static constexpr std::string_view GetWebUIName() {
+    return "GlicSelectionOverlayUntrusted";
+  }
+
+ private:
+  SelectionOverlayController& GetSelectionOverlayController();
+
+  // `selection::SelectionOverlayPageHandlerFactory`:
+  void CreatePageHandler(
+      mojo::PendingReceiver<selection::SelectionOverlayPageHandler> receiver,
+      mojo::PendingRemote<selection::SelectionOverlayPage> page) override;
+
+  mojo::Receiver<selection::SelectionOverlayPageHandlerFactory>
+      selection_page_factory_receiver_{this};
+
+  base::WeakPtrFactory<SelectionOverlayUntrustedUI> weak_factory_{this};
+
+  WEB_UI_CONTROLLER_TYPE_DECL();
+};
+
+}  // namespace glic
+
+#endif  // CHROME_BROWSER_GLIC_SELECTION_SELECTION_OVERLAY_UNTRUSTED_UI_H_
diff --git a/chrome/browser/glic/test_support/mock_local_hotkey_panel.h b/chrome/browser/glic/test_support/mock_local_hotkey_panel.h
index 2607166..f7c78b9b 100644
--- a/chrome/browser/glic/test_support/mock_local_hotkey_panel.h
+++ b/chrome/browser/glic/test_support/mock_local_hotkey_panel.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_GLIC_TEST_SUPPORT_MOCK_LOCAL_HOTKEY_PANEL_H_
 
 #include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
 #include "chrome/browser/glic/common/local_hotkey_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "ui/gfx/geometry/point.h"
@@ -24,7 +25,9 @@
   MOCK_METHOD(void, Close, (const CloseOptions& options), (override));
   MOCK_METHOD(bool, ActivateBrowser, (), (override));
   MOCK_METHOD(void, ShowTitleBarContextMenuAt, (gfx::Point), (override));
+#if !BUILDFLAG(IS_ANDROID)
   MOCK_METHOD(base::WeakPtr<views::View>, GetView, (), (override));
+#endif
 
   base::WeakPtr<LocalHotkeyManager::Panel> GetWeakPtr() {
     return weak_ptr_factory_.GetWeakPtr();
diff --git a/chrome/browser/glic/widget/glic_floating_ui.cc b/chrome/browser/glic/widget/glic_floating_ui.cc
index 34a3b51..902ec47e 100644
--- a/chrome/browser/glic/widget/glic_floating_ui.cc
+++ b/chrome/browser/glic/widget/glic_floating_ui.cc
@@ -451,12 +451,14 @@
   return GlicInactiveFloatingUi::From(*this);
 }
 
+#if !BUILDFLAG(IS_ANDROID)
 base::WeakPtr<views::View> GlicFloatingUi::GetView() {
   if (auto* glic_view = GetGlicView()) {
     return glic_view->GetWeakPtr();
   }
   return nullptr;
 }
+#endif
 
 void GlicFloatingUi::SwitchConversation(
     glic::mojom::ConversationInfoPtr info,
diff --git a/chrome/browser/glic/widget/glic_floating_ui.h b/chrome/browser/glic/widget/glic_floating_ui.h
index 3691a8c6..e18942eb 100644
--- a/chrome/browser/glic/widget/glic_floating_ui.h
+++ b/chrome/browser/glic/widget/glic_floating_ui.h
@@ -101,7 +101,9 @@
   bool HasFocus() override;
   bool ActivateBrowser() override;
   void ShowTitleBarContextMenuAt(gfx::Point event_loc) override;
+#if !BUILDFLAG(IS_ANDROID)
   base::WeakPtr<views::View> GetView() override;
+#endif
 
   // web_modal::WebContentsModalDialogManagerDelegate:
   web_modal::WebContentsModalDialogHost* GetWebContentsModalDialogHost(
diff --git a/chrome/browser/glic/widget/glic_inactive_floating_ui.cc b/chrome/browser/glic/widget/glic_inactive_floating_ui.cc
index e87077ca..e946e27 100644
--- a/chrome/browser/glic/widget/glic_inactive_floating_ui.cc
+++ b/chrome/browser/glic/widget/glic_inactive_floating_ui.cc
@@ -46,9 +46,11 @@
   NOTIMPLEMENTED();
 }
 
+#if !BUILDFLAG(IS_ANDROID)
 base::WeakPtr<views::View> GlicInactiveFloatingUi::GetView() {
   return nullptr;
 }
+#endif
 
 gfx::Size GlicInactiveFloatingUi::GetPanelSize() {
   return gfx::Size();
diff --git a/chrome/browser/glic/widget/glic_inactive_floating_ui.h b/chrome/browser/glic/widget/glic_inactive_floating_ui.h
index 063a58a5..4dca072 100644
--- a/chrome/browser/glic/widget/glic_inactive_floating_ui.h
+++ b/chrome/browser/glic/widget/glic_inactive_floating_ui.h
@@ -28,7 +28,9 @@
   std::unique_ptr<GlicUiEmbedder> CreateInactiveEmbedder() const override;
   void Focus() override;
   bool HasFocus() override;
+#if !BUILDFLAG(IS_ANDROID)
   base::WeakPtr<views::View> GetView() override;
+#endif
   mojom::PanelState GetPanelState() const override;
   gfx::Size GetPanelSize() override;
   std::string DescribeForTesting() override;
diff --git a/chrome/browser/glic/widget/glic_inactive_side_panel_ui.cc b/chrome/browser/glic/widget/glic_inactive_side_panel_ui.cc
index cc02de3..bbcf756 100644
--- a/chrome/browser/glic/widget/glic_inactive_side_panel_ui.cc
+++ b/chrome/browser/glic/widget/glic_inactive_side_panel_ui.cc
@@ -116,9 +116,11 @@
   glic_side_panel_coordinator->Close(options);
 }
 
+#if !BUILDFLAG(IS_ANDROID)
 base::WeakPtr<views::View> GlicInactiveSidePanelUi::GetView() {
   return nullptr;
 }
+#endif
 
 void GlicInactiveSidePanelUi::Focus() {
   // Do nothing. Inactive view doesn't have webcontents to set focus on.
diff --git a/chrome/browser/glic/widget/glic_inactive_side_panel_ui.h b/chrome/browser/glic/widget/glic_inactive_side_panel_ui.h
index 18751b5..691795a 100644
--- a/chrome/browser/glic/widget/glic_inactive_side_panel_ui.h
+++ b/chrome/browser/glic/widget/glic_inactive_side_panel_ui.h
@@ -7,7 +7,6 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
-#include "chrome/browser/glic/public/glic_side_panel_coordinator.h"
 #include "chrome/browser/glic/service/glic_ui_embedder.h"
 #include "chrome/browser/glic/widget/inactive_view_controller.h"
 #include "ui/gfx/image/image_skia.h"
@@ -19,6 +18,8 @@
 
 namespace glic {
 
+class GlicSidePanelCoordinator;
+
 // A GlicUiEmbedder for inactive Glic instances. This will show a
 // blurred screenshot of the previously active UI.
 class GlicInactiveSidePanelUi : public GlicUiEmbedder,
@@ -43,7 +44,9 @@
   bool HasFocus() override;
   std::string DescribeForTesting() override;
 
+#if !BUILDFLAG(IS_ANDROID)
   base::WeakPtr<views::View> GetView() override;
+#endif
   mojom::PanelState GetPanelState() const override;
   gfx::Size GetPanelSize() override;
 
diff --git a/chrome/browser/history/history_browsertest.cc b/chrome/browser/history/history_browsertest.cc
index d217027..d10b42bb 100644
--- a/chrome/browser/history/history_browsertest.cc
+++ b/chrome/browser/history/history_browsertest.cc
@@ -23,8 +23,6 @@
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history/history_tab_helper.h"
 #include "chrome/browser/history/history_test_utils.h"
-#include "chrome/browser/history_clusters/history_clusters_tab_helper.h"
-#include "chrome/browser/history_embeddings/history_embeddings_tab_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/chrome_navigation_ui_data.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
@@ -73,30 +71,11 @@
 
 namespace {
 
-class MockHistoryEmbeddingsTabHelper : public HistoryEmbeddingsTabHelper {
+class MockOnUpdatedHistoryForNavigationObserver {
  public:
-  explicit MockHistoryEmbeddingsTabHelper(content::WebContents* web_contents,
-                                          HistoryTabHelper* history_tab_helper)
-      : HistoryEmbeddingsTabHelper(web_contents, history_tab_helper) {}
-  ~MockHistoryEmbeddingsTabHelper() override = default;
-
   MOCK_METHOD(void,
               OnUpdatedHistoryForNavigation,
-              (int64_t, bool, base::Time, const GURL&),
-              (override));
-};
-
-class MockHistoryClustersTabHelper : public HistoryClustersTabHelper {
- public:
-  explicit MockHistoryClustersTabHelper(content::WebContents* web_contents,
-                                        HistoryTabHelper* history_tab_helper)
-      : HistoryClustersTabHelper(web_contents, history_tab_helper) {}
-  ~MockHistoryClustersTabHelper() override = default;
-
-  MOCK_METHOD(void,
-              OnUpdatedHistoryForNavigation,
-              (int64_t, bool, base::Time, const GURL&),
-              (override));
+              (int64_t, bool, base::Time, const GURL&));
 };
 
 // Used to test if the History Service Observer gets called for both
@@ -1430,68 +1409,31 @@
 }
 
 IN_PROC_BROWSER_TEST_P(History404BrowserTest,
-                       DoesNotNotifyHistoryEmbeddingsTabHelperOn404) {
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-
-  // The HistoryEmbeddingsTabHelper is created in ChromeContentBrowserClient, so
-  // it already exists in web_contents.
-  web_contents->RemoveUserData(HistoryEmbeddingsTabHelper::UserDataKey());
-  auto mock_helper = std::make_unique<MockHistoryEmbeddingsTabHelper>(
-      web_contents, HistoryTabHelper::FromWebContents(web_contents));
-  MockHistoryEmbeddingsTabHelper* mock_helper_ptr = mock_helper.get();
-  web_contents->SetUserData(HistoryEmbeddingsTabHelper::UserDataKey(),
-                            std::move(mock_helper));
-
+                       NoOnUpdatedHistoryForNavigationOn404) {
   history::HistoryService* history_service =
       HistoryServiceFactory::GetForProfile(browser()->profile(),
                                            ServiceAccessType::EXPLICIT_ACCESS);
+  HistoryTabHelper* history_tab_helper = HistoryTabHelper::FromWebContents(
+      browser()->tab_strip_model()->GetActiveWebContents());
+
+  testing::NiceMock<MockOnUpdatedHistoryForNavigationObserver> mock_observer;
+  base::CallbackListSubscription subscription =
+      history_tab_helper->RegisterOnUpdatedHistoryForNavigationCallback(
+          base::BindRepeating(&MockOnUpdatedHistoryForNavigationObserver::
+                                  OnUpdatedHistoryForNavigation,
+                              base::Unretained(&mock_observer)));
+
   ui_test_utils::WaitForHistoryToLoad(history_service);
 
-  // Regardless of whether the feature is enabled, HistoryEmbeddings shouldn't
-  // be notified on a 404 visit...
+  // The callback shouldn't be invoked on a 404 visit...
   GURL url404 = embedded_https_test_server().GetURL("/page404.html");
-  EXPECT_CALL(*mock_helper_ptr, OnUpdatedHistoryForNavigation(_, _, _, url404))
+  EXPECT_CALL(mock_observer, OnUpdatedHistoryForNavigation(_, _, _, url404))
       .Times(0);
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url404));
 
-  // ... but a non-404 visit should
+  // ... but a non-404 visit should invoke it.
   GURL url_non_404 = embedded_https_test_server().GetURL("/title1.html");
-  EXPECT_CALL(*mock_helper_ptr,
-              OnUpdatedHistoryForNavigation(_, _, _, url_non_404))
-      .Times(1);
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url_non_404));
-}
-
-IN_PROC_BROWSER_TEST_P(History404BrowserTest,
-                       DoesNotNotifyHistoryClustersTabHelperOn404) {
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-
-  // The HistoryClustersTabHelper is created in ChromeContentBrowserClient, so
-  // it already exists in web_contents.
-  web_contents->RemoveUserData(HistoryClustersTabHelper::UserDataKey());
-  auto mock_helper = std::make_unique<MockHistoryClustersTabHelper>(
-      web_contents, HistoryTabHelper::FromWebContents(web_contents));
-  MockHistoryClustersTabHelper* mock_helper_ptr = mock_helper.get();
-  web_contents->SetUserData(HistoryClustersTabHelper::UserDataKey(),
-                            std::move(mock_helper));
-
-  history::HistoryService* history_service =
-      HistoryServiceFactory::GetForProfile(browser()->profile(),
-                                           ServiceAccessType::EXPLICIT_ACCESS);
-  ui_test_utils::WaitForHistoryToLoad(history_service);
-
-  // Regardless of whether the feature is enabled, HistoryClusters shouldn't
-  // be notified on a 404 visit...
-  GURL url404 = embedded_https_test_server().GetURL("/page404.html");
-  EXPECT_CALL(*mock_helper_ptr, OnUpdatedHistoryForNavigation(_, _, _, url404))
-      .Times(0);
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url404));
-
-  // ... but a non-404 visit should
-  GURL url_non_404 = embedded_https_test_server().GetURL("/title1.html");
-  EXPECT_CALL(*mock_helper_ptr,
+  EXPECT_CALL(mock_observer,
               OnUpdatedHistoryForNavigation(_, _, _, url_non_404))
       .Times(1);
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url_non_404));
diff --git a/chrome/browser/install_verification/BUILD.gn b/chrome/browser/install_verification/BUILD.gn
new file mode 100644
index 0000000..ea41906
--- /dev/null
+++ b/chrome/browser/install_verification/BUILD.gn
@@ -0,0 +1,46 @@
+import("//build/config/compiler/compiler.gni")
+import("//testing/test.gni")
+
+source_set("install_verification") {
+  if (is_win) {
+    sources = [
+      "win/module_info.h",
+      "win/module_list.h",
+      "win/module_verification_common.h",
+    ]
+  }
+}
+
+source_set("impl") {
+  if (is_win) {
+    sources = [
+      "win/module_list.cc",
+      "win/module_verification_common.cc",
+    ]
+
+    deps = [
+      ":install_verification",
+      "//base",
+    ]
+  }
+}
+
+source_set("unit_tests") {
+  testonly = true
+  if (is_win) {
+    sources = [
+      "win/module_info_unittest.cc",
+      "win/module_list_unittest.cc",
+      "win/module_verification_test.cc",
+      "win/module_verification_test.h",
+    ]
+
+    deps = [
+      ":impl",
+      ":install_verification",
+      "//base",
+      "//testing/gtest",
+      "//third_party/abseil-cpp:absl",
+    ]
+  }
+}
diff --git a/chrome/browser/install_verification/DEPS b/chrome/browser/install_verification/DEPS
new file mode 100644
index 0000000..855dc84f
--- /dev/null
+++ b/chrome/browser/install_verification/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+  "-chrome/browser",
+  "+chrome/browser/install_verification",
+  "+base",
+]
diff --git a/chrome/browser/install_verification/win/module_verification_test.cc b/chrome/browser/install_verification/win/module_verification_test.cc
index 11138e9..4bafcb6 100644
--- a/chrome/browser/install_verification/win/module_verification_test.cc
+++ b/chrome/browser/install_verification/win/module_verification_test.cc
@@ -9,9 +9,12 @@
 #include <vector>
 
 #include "base/win/win_util.h"
+#include "chrome/browser/install_verification/win/module_info.h"
 #include "chrome/browser/install_verification/win/module_list.h"
 
-std::set<size_t> ModuleVerificationTest::reported_module_ids_;
+ModuleVerificationTest::ModuleVerificationTest() = default;
+
+ModuleVerificationTest::~ModuleVerificationTest() = default;
 
 void ModuleVerificationTest::SetUp() {
   reported_module_ids_.clear();
@@ -27,7 +30,6 @@
   return true;
 }
 
-// static
 void ModuleVerificationTest::ReportModule(size_t module_id) {
   reported_module_ids_.insert(module_id);
 }
diff --git a/chrome/browser/install_verification/win/module_verification_test.h b/chrome/browser/install_verification/win/module_verification_test.h
index 57f8981..5efe96d 100644
--- a/chrome/browser/install_verification/win/module_verification_test.h
+++ b/chrome/browser/install_verification/win/module_verification_test.h
@@ -8,21 +8,24 @@
 #include <stddef.h>
 
 #include <set>
-#include "chrome/browser/install_verification/win/module_info.h"
+
 #include "testing/gtest/include/gtest/gtest.h"
 
 struct ModuleInfo;
 
 class ModuleVerificationTest : public testing::Test {
  public:
+  ModuleVerificationTest();
+  ~ModuleVerificationTest() override;
+
   void SetUp() override;
 
  protected:
   bool GetLoadedModuleInfoSet(std::set<ModuleInfo>* loaded_module_info_set);
 
-  static void ReportModule(size_t module_id);
+  void ReportModule(size_t module_id);
 
-  static std::set<size_t> reported_module_ids_;
+  std::set<size_t> reported_module_ids_;
 };
 
 #endif  // CHROME_BROWSER_INSTALL_VERIFICATION_WIN_MODULE_VERIFICATION_TEST_H_
diff --git a/chrome/browser/navigation_predictor/BUILD.gn b/chrome/browser/navigation_predictor/BUILD.gn
index 7cbae76..baee824a 100644
--- a/chrome/browser/navigation_predictor/BUILD.gn
+++ b/chrome/browser/navigation_predictor/BUILD.gn
@@ -26,6 +26,7 @@
   deps = [
     ":navigation_predictor",
     "//chrome/browser/battery",
+    "//chrome/browser/predictors",
     "//chrome/browser/profiles:profile",
     "//chrome/browser/search_engines",
     "//content/public/browser",
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
index e4c1d64..6e5901e1 100644
--- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
+++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -1938,8 +1938,7 @@
           net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI ||
       connection_type ==
           net::NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET;
-  return IsBluetoothPowered() ||
-         (hasNetworkConnection && ::features::IsNearbyMdnsEnabled());
+  return IsBluetoothPowered() || hasNetworkConnection;
 }
 
 void NearbySharingServiceImpl::InvalidateSurfaceState() {
diff --git a/chrome/browser/new_tab_page/new_tab_page_realbox_interactive_uitest.cc b/chrome/browser/new_tab_page/new_tab_page_realbox_interactive_uitest.cc
index aa1b9b51..c9d50fc5 100644
--- a/chrome/browser/new_tab_page/new_tab_page_realbox_interactive_uitest.cc
+++ b/chrome/browser/new_tab_page/new_tab_page_realbox_interactive_uitest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <string_view>
+
 #include "base/check_deref.h"
 #include "base/test/scoped_feature_list.h"
 #include "build/buildflag.h"
@@ -19,6 +21,10 @@
 #include "components/user_education/common/user_education_features.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/omnibox_proto/model_mode.pb.h"
+#include "third_party/omnibox_proto/searchbox_config.pb.h"
+#include "third_party/omnibox_proto/tool_mode.pb.h"
+#include "third_party/omnibox_proto/types.pb.h"
 #include "ui/native_theme/mock_os_settings_provider.h"
 
 // To debug locally, you can run the test via:
@@ -43,6 +49,15 @@
 DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kNtpElementId);
 DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kGooglePageId);
 
+static constexpr std::string_view kModelFastLabel = "Fast";
+static constexpr std::string_view kModelAutoLabel = "Auto";
+static constexpr std::string_view kModelProLabel = "Pro";
+static constexpr std::string_view kHintText = "Ask anything";
+static constexpr std::string_view kInputTypeAddImage = "Add image";
+static constexpr std::string_view kInputTypeAddFile = "Add file";
+static constexpr std::string_view kToolCreateImages = "Create images";
+static constexpr std::string_view kToolCanvas = "Canvas";
+
 // Contains variables on which these tests may be parameterized. This approach
 // makes it easy to build sets of relevant tests, vs. the brute-force
 // testing::Combine() approach.
@@ -78,12 +93,42 @@
           /*url_loader_factory=*/nullptr, /*identity_manager=*/nullptr,
           AimEligibilityService::Configuration{});
 
+  auto* rule_set = mock_aim_eligibility_service->config().mutable_rule_set();
+  for (const auto input_type : {omnibox::InputType::INPUT_TYPE_LENS_IMAGE,
+                                omnibox::InputType::INPUT_TYPE_LENS_FILE}) {
+    rule_set->add_allowed_input_types(input_type);
+  }
+  for (const auto tool : {omnibox::ToolMode::TOOL_MODE_CANVAS,
+                          omnibox::ToolMode::TOOL_MODE_IMAGE_GEN}) {
+    rule_set->add_allowed_tools(tool);
+  }
+  for (const auto model : {omnibox::ModelMode::MODEL_MODE_GEMINI_REGULAR,
+                           omnibox::ModelMode::MODEL_MODE_GEMINI_PRO}) {
+    rule_set->add_allowed_models(model);
+  }
+
+  auto* regular_config =
+      mock_aim_eligibility_service->config().add_model_configs();
+  regular_config->set_model(omnibox::ModelMode::MODEL_MODE_GEMINI_REGULAR);
+  regular_config->set_menu_label(std::string(kModelFastLabel));
+
+  auto* pro_config = mock_aim_eligibility_service->config().add_model_configs();
+  pro_config->set_model(omnibox::ModelMode::MODEL_MODE_GEMINI_PRO);
+  pro_config->set_menu_label(std::string(kModelProLabel));
+  mock_aim_eligibility_service->config().set_hint_text(std::string(kHintText));
+
   ON_CALL(*mock_aim_eligibility_service, IsAimEligible())
       .WillByDefault(testing::Return(true));
   ON_CALL(*mock_aim_eligibility_service, IsAimLocallyEligible())
       .WillByDefault(testing::Return(true));
   ON_CALL(*mock_aim_eligibility_service, IsServerEligibilityEnabled())
       .WillByDefault(testing::Return(true));
+  ON_CALL(*mock_aim_eligibility_service, IsCanvasEligible())
+      .WillByDefault(testing::Return(true));
+  ON_CALL(*mock_aim_eligibility_service, IsDeepSearchEligible())
+      .WillByDefault(testing::Return(true));
+  ON_CALL(*mock_aim_eligibility_service, IsCreateImagesEligible())
+      .WillByDefault(testing::Return(true));
 
   return std::move(mock_aim_eligibility_service);
 }
@@ -221,6 +266,20 @@
       return info.param.ToString();
     });
 
+using NtpRealboxNextUiTest = NtpRealboxUiTest;
+
+INSTANTIATE_TEST_SUITE_P(
+    ,
+    NtpRealboxNextUiTest,
+    ValuesIn(std::vector<NtpRealboxUiTestParams>{
+        {
+            .layout_mode = RealboxLayoutMode::kCompact,
+        },
+    }),
+    [](const testing::TestParamInfo<NtpRealboxUiTestParams>& info) {
+      return info.param.ToString();
+    });
+
 // TODO(crbug.com/454761015): Re-enable after fixing.
 IN_PROC_BROWSER_TEST_P(NtpRealboxUiTest, DISABLED_Screenshots) {
   // Force a consistent window size to exercise realbox layout within New Tab
@@ -266,11 +325,7 @@
                           /*baseline_cl=*/"7055903")));
 }
 
-IN_PROC_BROWSER_TEST_P(NtpRealboxUiTest, ContextualEntrypointOpensComposebox) {
-  if (!GetParam().compose_button_enabled) {
-    GTEST_SKIP() << "Compose button not enabled for this parameter set";
-  }
-
+IN_PROC_BROWSER_TEST_P(NtpRealboxNextUiTest, AimButtonOpensComposebox) {
   DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kComposeboxDialogOpenEvent);
 
   const DeepQuery kRealbox = {"ntp-app", "cr-searchbox", "#inputWrapper"};
@@ -289,10 +344,108 @@
       AddInstrumentedTab(kGooglePageId, GURL("https://www.google.com")),
       // 2. Load NTP.
       AddInstrumentedTab(kNtpElementId, GURL(chrome::kChromeUINewTabURL)),
-      // 3. Assert NTP has loaded by waiting for the realbox to render.
+      // 3. Assert NTP has loaded by waiting for the realbox and compose button
+      // to render.
       WaitForElementToRender(kNtpElementId, kRealbox),
+      WaitForElementToRender(kNtpElementId, kComposeButton),
       // 4. Click on the compose button.
       ClickElement(kNtpElementId, kComposeButton),
       // 5. Observe/assert that the contextual dialog is open.
       WaitForStateChange(kNtpElementId, composebox_dialog_open));
 }
+
+IN_PROC_BROWSER_TEST_P(NtpRealboxNextUiTest,
+                       ContextualEntrypointMenuHasOptions) {
+  DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kContextMenuOpenEvent);
+
+  const DeepQuery kRealbox = {"ntp-app", "cr-searchbox", "#inputWrapper"};
+  const DeepQuery kContextualEntrypoint = {"ntp-app",
+                                           "cr-searchbox",
+                                           "contextual-entrypoint-and-carousel",
+                                           "#contextEntrypoint",
+                                           "#entrypointButton",
+                                           "#entrypoint"};
+  const DeepQuery kContextMenuDialog = {"ntp-app",
+                                        "cr-searchbox",
+                                        "contextual-entrypoint-and-carousel",
+                                        "#contextEntrypoint",
+                                        "#menu",
+                                        "#menu",
+                                        "#dialog"};
+
+  WebContentsInteractionTestUtil::StateChange context_menu_open;
+  context_menu_open.event = kContextMenuOpenEvent;
+  context_menu_open.where = kContextMenuDialog;
+  context_menu_open.test_function = "(el) => el && el.open";
+
+  const DeepQuery kImageUploadItem = {"ntp-app",
+                                      "cr-searchbox",
+                                      "contextual-entrypoint-and-carousel",
+                                      "#contextEntrypoint",
+                                      "#menu",
+                                      "#imageUpload"};
+  const DeepQuery kFileUploadItem = {"ntp-app",
+                                     "cr-searchbox",
+                                     "contextual-entrypoint-and-carousel",
+                                     "#contextEntrypoint",
+                                     "#menu",
+                                     "#fileUpload"};
+  const DeepQuery kCreateImagesItem = {"ntp-app",
+                                       "cr-searchbox",
+                                       "contextual-entrypoint-and-carousel",
+                                       "#contextEntrypoint",
+                                       "#menu",
+                                       "button[data-mode='4']"};
+  const DeepQuery kCanvasItem = {"ntp-app",
+                                 "cr-searchbox",
+                                 "contextual-entrypoint-and-carousel",
+                                 "#contextEntrypoint",
+                                 "#menu",
+                                 "button[data-mode='2']"};
+  const DeepQuery kFastModelItem = {"ntp-app",
+                                    "cr-searchbox",
+                                    "contextual-entrypoint-and-carousel",
+                                    "#contextEntrypoint",
+                                    "#menu",
+                                    "button[data-model='1']"};
+  const DeepQuery kProModelItem = {"ntp-app",
+                                   "cr-searchbox",
+                                   "contextual-entrypoint-and-carousel",
+                                   "#contextEntrypoint",
+                                   "#menu",
+                                   "button[data-model='2']"};
+
+  RunTestSequence(
+      AddInstrumentedTab(kNtpElementId, GURL(chrome::kChromeUINewTabURL)),
+      WaitForElementToRender(kNtpElementId, kRealbox),
+      WaitForElementToRender(kNtpElementId, kContextualEntrypoint),
+      ClickElement(kNtpElementId, kContextualEntrypoint),
+      WaitForStateChange(kNtpElementId, context_menu_open),
+      WaitForElementToRender(kNtpElementId, kImageUploadItem),
+      CheckJsResultAt(kNtpElementId, kImageUploadItem,
+                      "(el) => el.textContent.includes('" +
+                          std::string(kInputTypeAddImage) + "')"),
+      WaitForElementToRender(kNtpElementId, kFileUploadItem),
+      CheckJsResultAt(kNtpElementId, kFileUploadItem,
+                      "(el) => el.textContent.includes('" +
+                          std::string(kInputTypeAddFile) + "')"),
+      WaitForElementToRender(kNtpElementId, kCreateImagesItem),
+      CheckJsResultAt(kNtpElementId, kCreateImagesItem,
+                      "(el) => el.textContent.includes('" +
+                          std::string(kToolCreateImages) + "')"),
+      WaitForElementToRender(kNtpElementId, kCanvasItem),
+      CheckJsResultAt(kNtpElementId, kCanvasItem,
+                      "(el) => el.textContent.includes('" +
+                          std::string(kToolCanvas) + "')"),
+      WaitForElementToRender(kNtpElementId, kFastModelItem),
+      CheckJsResultAt(kNtpElementId, kFastModelItem,
+                      "(el) => el.textContent.includes('" +
+                          std::string(kModelFastLabel) +
+                          "') || "
+                          "el.textContent.includes('" +
+                          std::string(kModelAutoLabel) + "')"),
+      WaitForElementToRender(kNtpElementId, kProModelItem),
+      CheckJsResultAt(kNtpElementId, kProModelItem,
+                      "(el) => el.textContent.includes('" +
+                          std::string(kModelProLabel) + "')"));
+}
diff --git a/chrome/browser/notifications/scheduler/tips_agent_android.cc b/chrome/browser/notifications/scheduler/tips_agent_android.cc
index e9c3cd15..82d9a212 100644
--- a/chrome/browser/notifications/scheduler/tips_agent_android.cc
+++ b/chrome/browser/notifications/scheduler/tips_agent_android.cc
@@ -51,6 +51,8 @@
     return notifications::TipsNotificationsFeatureType::kSignin;
   } else if (label == segmentation_platform::kCreateTabGroups) {
     return notifications::TipsNotificationsFeatureType::kCreateTabGroups;
+  } else if (label == segmentation_platform::kCustomizeMVT) {
+    return notifications::TipsNotificationsFeatureType::kCustomizeMVT;
   } else {
     NOTREACHED();
   }
@@ -181,7 +183,7 @@
       segmentation_platform::processing::ProcessedValue(
           bottom_omnibox_tip_shown));
 
-  // V2 Tips: Password Autofill, Signin
+  // V2 Tips: Password Autofill, Signin, Create Tab Groups, Customize MVT
 
   bool is_user_signed_in =
       IdentityManagerFactory::GetForProfile(profile)->HasPrimaryAccount(
@@ -211,6 +213,13 @@
       segmentation_platform::processing::ProcessedValue(
           create_tab_groups_tip_shown));
 
+  bool customize_mvt_tip_shown =
+      pref_service->GetBoolean(prefs::kAndroidTipNotificationShownCustomizeMVT);
+  input_context->metadata_args.emplace(
+      segmentation_platform::kCustomizeMVTTipShown,
+      segmentation_platform::processing::ProcessedValue(
+          customize_mvt_tip_shown));
+
   segmentation_platform_service->GetClassificationResult(
       segmentation_platform::kTipsNotificationsRankerKey, prediction_options,
       input_context,
diff --git a/chrome/browser/notifications/system_notification_helper.h b/chrome/browser/notifications/system_notification_helper.h
index 965df7b8..904232c 100644
--- a/chrome/browser/notifications/system_notification_helper.h
+++ b/chrome/browser/notifications/system_notification_helper.h
@@ -41,7 +41,7 @@
   // Gets or creates a NotificationDisplayService for system notifications.
   NotificationDisplayService* GetSystemService();
 
-  // The global system NotificationDisaplyService, not bound to any profile.
+  // The global system NotificationDisplayService, not bound to any profile.
   std::unique_ptr<NotificationDisplayService> system_service_;
 };
 
diff --git a/chrome/browser/ntp_customization/java/res/layout/ntp_customization_theme_preview_dialog_layout.xml b/chrome/browser/ntp_customization/java/res/layout/ntp_customization_theme_preview_dialog_layout.xml
index 2986934..82849893 100644
--- a/chrome/browser/ntp_customization/java/res/layout/ntp_customization_theme_preview_dialog_layout.xml
+++ b/chrome/browser/ntp_customization/java/res/layout/ntp_customization_theme_preview_dialog_layout.xml
@@ -122,6 +122,7 @@
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintBottom_toBottomOf="parent" />
 
+    <!-- Save button constrained to Cancel button, so it moves automatically when Cancel moves -->
     <org.chromium.ui.widget.ButtonCompat
         android:id="@+id/save_button"
         android:layout_width="wrap_content"
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/NtpThemeProperty.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/NtpThemeProperty.java
index ee31ab5..01653d4 100644
--- a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/NtpThemeProperty.java
+++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/NtpThemeProperty.java
@@ -82,6 +82,9 @@
     public static final PropertyModel.WritableIntPropertyKey SEARCH_BOX_TOP_MARGIN =
             new PropertyModel.WritableIntPropertyKey();
 
+    // The bottom margin of the buttons in pixels.
+    public static final PropertyModel.WritableIntPropertyKey BUTTON_BOTTOM_MARGIN =
+            new PropertyModel.WritableIntPropertyKey();
     public static final PropertyKey[] THEME_KEYS =
             new PropertyKey[] {
                 LEARN_MORE_BUTTON_CLICK_LISTENER,
@@ -103,6 +106,7 @@
                 SIDE_AND_BOTTOM_INSETS,
                 SEARCH_BOX_WIDTH,
                 SEARCH_BOX_HEIGHT,
-                SEARCH_BOX_TOP_MARGIN
+                SEARCH_BOX_TOP_MARGIN,
+                BUTTON_BOTTOM_MARGIN
             };
 }
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewCoordinator.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewCoordinator.java
index 0396cd3..c180a24 100644
--- a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewCoordinator.java
+++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewCoordinator.java
@@ -7,6 +7,7 @@
 import static org.chromium.build.NullUtil.assumeNonNull;
 import static org.chromium.chrome.browser.ntp_customization.NtpCustomizationUtils.doesDefaultSearchEngineHaveLogo;
 import static org.chromium.chrome.browser.ntp_customization.NtpCustomizationUtils.getSearchBoxTwoSideMargin;
+import static org.chromium.chrome.browser.ntp_customization.theme.NtpThemeProperty.BUTTON_BOTTOM_MARGIN;
 import static org.chromium.chrome.browser.ntp_customization.theme.NtpThemeProperty.LOGO_BITMAP;
 import static org.chromium.chrome.browser.ntp_customization.theme.NtpThemeProperty.LOGO_PARAMS;
 import static org.chromium.chrome.browser.ntp_customization.theme.NtpThemeProperty.LOGO_VISIBILITY;
@@ -62,6 +63,7 @@
     private final boolean mShouldShowLogoAndSearchBox;
     private final Activity mActivity;
     private final UiConfig mUiConfig;
+    private final int mButtonBottomMargin;
     private View.@Nullable OnLayoutChangeListener mLayoutChangeListener;
     private @Nullable UploadImagePreviewLayout mPreviewLayout;
     private @Nullable CropImageView mCropImageView;
@@ -109,6 +111,10 @@
         mCropImageView = mPreviewLayout.findViewById(R.id.preview_image);
         mToolBarHeight =
                 mActivity.getResources().getDimensionPixelSize(R.dimen.toolbar_height_no_shadow);
+        mButtonBottomMargin =
+                mActivity
+                        .getResources()
+                        .getDimensionPixelSize(R.dimen.ntp_customization_back_button_margin_start);
 
         mUiConfig = new UiConfig(mPreviewLayout);
         mShouldShowLogoAndSearchBox =
@@ -191,6 +197,13 @@
                 new Rect(combinedInsets.left, 0, combinedInsets.right, bottomInsetForPadding);
         mPreviewPropertyModel.set(NtpThemeProperty.SIDE_AND_BOTTOM_INSETS, sideAndBottomInsets);
 
+        if (!hasTappableNavBar) {
+            // Since bottom padding is 0, the layout extends to the very bottom edge of the screen.
+            // Elevates the buttons by adding the navigation bar height to their base margin,
+            // preventing the gesture handle from overlapping the buttons.
+            mPreviewPropertyModel.set(
+                    BUTTON_BOTTOM_MARGIN, mButtonBottomMargin + combinedInsets.bottom);
+        }
         // Consumes the insets since the root view already adjusted their paddings.
         return new WindowInsetsCompat.Builder(windowInsetsCompat)
                 .setInsets(WindowInsetsCompat.Type.statusBars(), Insets.NONE)
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewLayout.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewLayout.java
index 53799913..13162000 100644
--- a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewLayout.java
+++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewLayout.java
@@ -31,8 +31,9 @@
 public class UploadImagePreviewLayout extends ConstraintLayout {
     private static final int GOOGLE_LOGO_TINT_COLOR = Color.WHITE;
     private ImageView mLogoView;
-    private @Nullable View mSearchBoxView;
     private Guideline mGuidelineTop;
+    private View mCancelButton;
+    private @Nullable View mSearchBoxView;
 
     public UploadImagePreviewLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -44,6 +45,7 @@
         mLogoView = findViewById(R.id.default_search_engine_logo);
         mGuidelineTop = findViewById(R.id.guideline_top);
         mSearchBoxView = findViewById(R.id.search_box_container);
+        mCancelButton = findViewById(R.id.cancel_button);
 
         View searchBox = findViewById(R.id.search_box);
         Drawable background = searchBox.getBackground();
@@ -102,6 +104,18 @@
         setPadding(insets.left, getPaddingTop(), insets.right, insets.bottom);
     }
 
+    void setButtonBottomMargin(int bottomMargin) {
+        if (mCancelButton == null) return;
+
+        ViewGroup.LayoutParams params = mCancelButton.getLayoutParams();
+        if (params instanceof MarginLayoutParams marginParams) {
+            if (marginParams.bottomMargin != bottomMargin) {
+                marginParams.bottomMargin = bottomMargin;
+                mCancelButton.setLayoutParams(marginParams);
+            }
+        }
+    }
+
     void setSearchBoxWidth(int widthPx) {
         if (mSearchBoxView == null) return;
 
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewLayoutViewBinder.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewLayoutViewBinder.java
index f478776..2e7f29a 100644
--- a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewLayoutViewBinder.java
+++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewLayoutViewBinder.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.ntp_customization.theme.upload_image;
 
 import static org.chromium.chrome.browser.ntp_customization.theme.NtpThemeProperty.BITMAP_FOR_PREVIEW;
+import static org.chromium.chrome.browser.ntp_customization.theme.NtpThemeProperty.BUTTON_BOTTOM_MARGIN;
 import static org.chromium.chrome.browser.ntp_customization.theme.NtpThemeProperty.LOGO_BITMAP;
 import static org.chromium.chrome.browser.ntp_customization.theme.NtpThemeProperty.LOGO_PARAMS;
 import static org.chromium.chrome.browser.ntp_customization.theme.NtpThemeProperty.LOGO_VISIBILITY;
@@ -55,6 +56,8 @@
             layout.setSearchBoxHeight(model.get(SEARCH_BOX_HEIGHT));
         } else if (propertyKey == SEARCH_BOX_TOP_MARGIN) {
             layout.setSearchBoxTopMargin(model.get(SEARCH_BOX_TOP_MARGIN));
+        } else if (propertyKey == BUTTON_BOTTOM_MARGIN) {
+            layout.setButtonBottomMargin(model.get(BUTTON_BOTTOM_MARGIN));
         }
     }
 }
diff --git a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewCoordinatorUnitTest.java b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewCoordinatorUnitTest.java
index 6ffade7..9d88131 100644
--- a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewCoordinatorUnitTest.java
+++ b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/theme/upload_image/UploadImagePreviewCoordinatorUnitTest.java
@@ -536,105 +536,66 @@
     @Test
     public void testOnApplyWindowInsets_ThreeButtonNavigation_Portrait() {
         // Setup insets representing 3-button navigation (tappable bottom bar)
-        int top = 20;
-        int bottom = 100;
-        int left = 0;
-        int right = 0;
-        Insets systemBars = Insets.of(left, top, right, bottom);
-        Insets navigationBars = Insets.of(0, 0, 0, bottom);
-        Insets tappableElement = Insets.of(0, top, 0, bottom);
-
-        WindowInsetsCompat insets =
-                new WindowInsetsCompat.Builder()
-                        .setInsets(WindowInsetsCompat.Type.systemBars(), systemBars)
-                        .setInsets(WindowInsetsCompat.Type.navigationBars(), navigationBars)
-                        .setInsets(WindowInsetsCompat.Type.tappableElement(), tappableElement)
-                        .build();
-        int expectedTopGuideline = mToolbarHeight + top;
-        // For 3-button navigation, the bottom inset should be applied as padding
-        Rect expectedSideAndBottom = new Rect(left, 0, right, bottom);
-
-        WindowInsetsCompat result =
-                mUploadImagePreviewCoordinator.onApplyWindowInsets(mCropImageView, insets);
-
-        assertTrue(EdgeToEdgeUtils.hasTappableNavigationBarFromInsets(insets));
-        verifyPaddingAndInsetsConsumed(result, expectedTopGuideline, expectedSideAndBottom);
+        verifyWindowInsetsApplied(
+                /* topInset= */ 20,
+                /* bottomInset= */ 100,
+                /* leftInset= */ 0,
+                /* rightInset= */ 0,
+                /* navigationBars= */ Insets.of(0, 0, 0, 100),
+                /* tappableElement= */ Insets.of(0, 20, 0, 100),
+                /* expectTappable= */ true);
     }
 
     @Test
     public void testOnApplyWindowInsets_GestureNavigation_Portrait() {
         // Setup insets representing Gesture navigation
-        int top = 20;
-        int bottom = 40;
-        int left = 0;
-        int right = 0;
-        Insets systemBars = Insets.of(left, top, right, bottom);
-        Insets navigationBars = Insets.of(0, 0, 0, bottom);
-        Insets tappableElement = Insets.of(0, top, 0, 0);
-
-        WindowInsetsCompat insets =
-                new WindowInsetsCompat.Builder()
-                        .setInsets(WindowInsetsCompat.Type.systemBars(), systemBars)
-                        .setInsets(WindowInsetsCompat.Type.navigationBars(), navigationBars)
-                        .setInsets(WindowInsetsCompat.Type.tappableElement(), tappableElement)
-                        .build();
-
-        int expectedTopGuideline = mToolbarHeight + top;
-        // For Gesture navigation, the bottom inset should not be applied (padding = 0)
-        Rect expectedSideAndBottom = new Rect(left, 0, right, 0);
-
-        WindowInsetsCompat result =
-                mUploadImagePreviewCoordinator.onApplyWindowInsets(mCropImageView, insets);
-
-        assertFalse(EdgeToEdgeUtils.hasTappableNavigationBarFromInsets(insets));
-        verifyPaddingAndInsetsConsumed(result, expectedTopGuideline, expectedSideAndBottom);
+        verifyWindowInsetsApplied(
+                /* topInset= */ 20,
+                /* bottomInset= */ 40,
+                /* leftInset= */ 0,
+                /* rightInset= */ 0,
+                /* navigationBars= */ Insets.of(0, 0, 0, 40),
+                /* tappableElement= */ Insets.of(0, 20, 0, 0),
+                /* expectTappable= */ false);
     }
 
     @Test
     public void testOnApplyWindowInsets_ThreeButtonNavigation_Landscape() {
         // Setup insets representing 3-button navigation in Landscape (Nav bar on the Right)
-        int top = 20; // Status bar at top
-        int bottom = 0; // No navigation bar at bottom
-        int left = 0;
-        int right = 100; // Navigation bar is on the right side
-
-        Insets systemBars = Insets.of(left, top, right, bottom);
-        Insets navigationBars = Insets.of(0, 0, right, 0);
-        Insets tappableElement = Insets.of(0, top, right, 0);
-
-        WindowInsetsCompat insets =
-                new WindowInsetsCompat.Builder()
-                        .setInsets(WindowInsetsCompat.Type.systemBars(), systemBars)
-                        .setInsets(WindowInsetsCompat.Type.navigationBars(), navigationBars)
-                        .setInsets(WindowInsetsCompat.Type.tappableElement(), tappableElement)
-                        .build();
-
-        int expectedTopGuideline = mToolbarHeight + top;
-
-        // In Landscape 3-button, the bottom padding is 0 (physically no bar there),
-        // but the right inset is preserved in the Rect.
-        Rect expectedSideAndBottom = new Rect(left, 0, right, bottom);
-
-        WindowInsetsCompat result =
-                mUploadImagePreviewCoordinator.onApplyWindowInsets(mCropImageView, insets);
-
-        assertTrue(EdgeToEdgeUtils.hasTappableNavigationBarFromInsets(insets));
-        verifyPaddingAndInsetsConsumed(result, expectedTopGuideline, expectedSideAndBottom);
+        verifyWindowInsetsApplied(
+                /* topInset= */ 20,
+                /* bottomInset= */ 0,
+                /* leftInset= */ 0,
+                /* rightInset= */ 100,
+                /* navigationBars= */ Insets.of(0, 0, 100, 0),
+                /* tappableElement= */ Insets.of(0, 20, 100, 0),
+                /* expectTappable= */ true);
     }
 
     @Test
     public void testOnApplyWindowInsets_GestureNavigation_Landscape() {
         // Setup insets representing Gesture navigation in Landscape
-        int top = 20;
-        int bottom = 20; // Small gesture handle at the bottom
-        int left = 0;
-        int right = 0; // Gestures usually don't have a solid bar on the right
+        verifyWindowInsetsApplied(
+                /* topInset= */ 20,
+                /* bottomInset= */ 20,
+                /* leftInset= */ 0,
+                /* rightInset= */ 0,
+                /* navigationBars= */ Insets.of(0, 0, 0, 20),
+                /* tappableElement= */ Insets.of(0, 20, 0, 0),
+                /* expectTappable= */ false);
+    }
 
-        Insets systemBars = Insets.of(left, top, right, bottom);
-        Insets navigationBars = Insets.of(0, 0, 0, bottom);
-        // Tappable element is 0 at bottom for gestures
-        Insets tappableElement = Insets.of(0, top, 0, 0);
+    /** Helper method that centralizes the Arrange/Act/Assert for window insets testing. */
+    private void verifyWindowInsetsApplied(
+            int topInset,
+            int bottomInset,
+            int leftInset,
+            int rightInset,
+            Insets navigationBars,
+            Insets tappableElement,
+            boolean expectTappable) {
 
+        Insets systemBars = Insets.of(leftInset, topInset, rightInset, bottomInset);
         WindowInsetsCompat insets =
                 new WindowInsetsCompat.Builder()
                         .setInsets(WindowInsetsCompat.Type.systemBars(), systemBars)
@@ -642,46 +603,56 @@
                         .setInsets(WindowInsetsCompat.Type.tappableElement(), tappableElement)
                         .build();
 
-        int expectedTopGuideline = mToolbarHeight + top;
-
-        // For Gesture navigation, bottom padding is 0 (Edge-to-Edge).
-        // Right is 0 because there is no bar.
-        Rect expectedSideAndBottom = new Rect(left, 0, right, 0);
+        PropertyModel model = mUploadImagePreviewCoordinator.getPropertyModelForTesting();
+        int buttonBottomMargin = model.get(NtpThemeProperty.BUTTON_BOTTOM_MARGIN);
 
         WindowInsetsCompat result =
                 mUploadImagePreviewCoordinator.onApplyWindowInsets(mCropImageView, insets);
 
-        assertFalse(EdgeToEdgeUtils.hasTappableNavigationBarFromInsets(insets));
-        verifyPaddingAndInsetsConsumed(result, expectedTopGuideline, expectedSideAndBottom);
-    }
+        // Verifies the edge-to-edge behavior
+        assertEquals(
+                "Tappable navigation bar evaluation failed.",
+                expectTappable,
+                EdgeToEdgeUtils.hasTappableNavigationBarFromInsets(insets));
 
-    void verifyPaddingAndInsetsConsumed(
-            WindowInsetsCompat insets, int expectedTopGuideline, Rect expectedSideAndBottom) {
-        // Verifies PropertyModel updates
-        PropertyModel model = mUploadImagePreviewCoordinator.getPropertyModelForTesting();
+        // Verifies inset consumption
+        assertEquals(Insets.NONE, result.getInsets(WindowInsetsCompat.Type.statusBars()));
+        assertEquals(Insets.NONE, result.getInsets(WindowInsetsCompat.Type.navigationBars()));
+        assertEquals(Insets.NONE, result.getInsets(WindowInsetsCompat.Type.displayCutout()));
+
+        // Verifies the paddings
+        int expectedTopGuideline = mToolbarHeight + topInset;
+        int expectedBottomPadding = expectTappable ? bottomInset : 0;
+        Rect expectedSideAndBottom = new Rect(leftInset, 0, rightInset, expectedBottomPadding);
+
         assertEquals(
                 "Top guideline should include toolbar height + top inset",
                 expectedTopGuideline,
                 model.get(NtpThemeProperty.TOP_GUIDELINE_BEGIN));
 
         assertEquals(
-                "Bottom inset should be 0 for gesture nav (Edge-to-Edge), but sides should remain",
+                "Padding rect should match expected side and bottom logic",
                 expectedSideAndBottom,
                 model.get(NtpThemeProperty.SIDE_AND_BOTTOM_INSETS));
 
-        // Verifies that the method consumed the specific insets it is responsible for
-        assertEquals(
-                "Status bars should be consumed in the returned insets",
-                Insets.NONE,
-                insets.getInsets(WindowInsetsCompat.Type.statusBars()));
-        assertEquals(
-                "Navigation bars should be consumed in the returned insets",
-                Insets.NONE,
-                insets.getInsets(WindowInsetsCompat.Type.navigationBars()));
-        assertEquals(
-                "Display cutout should be consumed in the returned insets",
-                Insets.NONE,
-                insets.getInsets(WindowInsetsCompat.Type.displayCutout()));
+        // Verifies the bottom margin of buttons
+        if (expectTappable) {
+            assertEquals(
+                    "Button margin should remain unchanged for 3-button nav, as padding pushes it"
+                        + " up.",
+                    buttonBottomMargin,
+                    model.get(NtpThemeProperty.BUTTON_BOTTOM_MARGIN));
+        } else {
+            int baseButtonBottomMargin =
+                    mActivity
+                            .getResources()
+                            .getDimensionPixelSize(
+                                    R.dimen.ntp_customization_back_button_margin_start);
+            assertEquals(
+                    "Button margin should be elevated by the inset for gesture nav.",
+                    baseButtonBottomMargin + bottomInset,
+                    model.get(NtpThemeProperty.BUTTON_BOTTOM_MARGIN));
+        }
     }
 
     /**
diff --git a/chrome/browser/predictors/BUILD.gn b/chrome/browser/predictors/BUILD.gn
new file mode 100644
index 0000000..44a99e6
--- /dev/null
+++ b/chrome/browser/predictors/BUILD.gn
@@ -0,0 +1,214 @@
+# Copyright 2026 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//extensions/buildflags/buildflags.gni")
+import("//third_party/protobuf/proto_library.gni")
+
+assert(is_win || is_mac || is_linux || is_chromeos || is_android)
+
+proto_library("resource_prefetch_predictor_proto") {
+  sources = [ "resource_prefetch_predictor.proto" ]
+}
+
+source_set("config") {
+  sources = [
+    "loading_predictor_config.cc",
+    "loading_predictor_config.h",
+    "predictors_features.cc",
+    "predictors_features.h",
+  ]
+  public_deps = [ "//base" ]
+  deps = [
+    "//chrome/browser/preloading:prefs",
+    "//chrome/browser/profiles:profile",
+    "//third_party/blink/public/common:headers",
+  ]
+}
+
+source_set("predictors") {
+  sources = [
+    "autocomplete_action_predictor.h",
+    "autocomplete_action_predictor_factory.h",
+    "autocomplete_action_predictor_table.h",
+    "loading_data_collector.h",
+    "loading_predictor.h",
+    "loading_predictor_factory.h",
+    "loading_predictor_tab_helper.h",
+    "loading_stats_collector.h",
+    "network_hints_handler_impl.h",
+    "perform_network_context_prefetch.h",
+    "predictor_database.h",
+    "predictor_database_factory.h",
+    "predictors_enums.h",
+    "predictors_switches.h",
+    "predictors_traffic_annotations.h",
+    "prefetch_manager.h",
+    "prefetch_traffic_annotation.h",
+    "resource_prefetch_predictor.h",
+    "resource_prefetch_predictor_tables.h",
+  ]
+  public_deps = [
+    ":resource_prefetch_predictor_proto",
+    "lcp_critical_path_predictor:headers",
+    "//base",
+    "//chrome/browser/profiles:profile",
+    "//components/history/core/browser",
+    "//components/keyed_service/core",
+    "//components/network_hints/common:mojo_bindings",
+    "//components/optimization_guide/core",
+    "//components/sqlite_proto",
+    "//content/public/browser",
+    "//net",
+    "//services/metrics/public/cpp:metrics_cpp",
+    "//services/network/public/mojom",
+    "//third_party/blink/public/common:headers",
+    "//url",
+  ]
+}
+
+source_set("impl") {
+  sources = [
+    "autocomplete_action_predictor.cc",
+    "autocomplete_action_predictor_factory.cc",
+    "autocomplete_action_predictor_table.cc",
+    "loading_data_collector.cc",
+    "loading_predictor.cc",
+    "loading_predictor_factory.cc",
+    "loading_predictor_tab_helper.cc",
+    "loading_stats_collector.cc",
+    "network_hints_handler_impl.cc",
+    "perform_network_context_prefetch.cc",
+    "predictor_database.cc",
+    "predictor_database_factory.cc",
+    "predictors_switches.cc",
+    "prefetch_manager.cc",
+    "resource_prefetch_predictor.cc",
+    "resource_prefetch_predictor_tables.cc",
+  ]
+  public_deps = [ "//chrome/browser:browser_public_dependencies" ]
+  deps = [
+    ":config",
+    ":predictors",
+    "lcp_critical_path_predictor:impl",
+    "//chrome/browser:browser_process",
+    "//chrome/browser/history",
+    "//chrome/browser/optimization_guide",
+    "//chrome/browser/preloading",
+    "//chrome/browser/preloading:prefs",
+    "//chrome/browser/preloading/prefetch/no_state_prefetch",
+    "//chrome/browser/profiles:profile",
+    "//chrome/common",
+    "//components/embedder_support",
+    "//components/embedder_support:user_agent",
+    "//components/google/core/common",
+    "//components/language/core/browser",
+    "//components/no_state_prefetch/browser",
+    "//components/omnibox/browser",
+    "//components/omnibox/common",
+    "//components/optimization_guide/core",
+    "//components/optimization_guide/proto:optimization_guide_proto",
+    "//components/prefs",
+    "//components/variations/net",
+    "//extensions/buildflags",
+    "//services/network/public/cpp",
+    "//sql",
+    "//third_party/blink/public/common:headers",
+    "//ui/base",
+  ]
+}
+
+source_set("test_support") {
+  testonly = true
+  sources = [
+    "loading_test_util.cc",
+    "loading_test_util.h",
+  ]
+  public_deps = [
+    ":predictors",
+    "lcp_critical_path_predictor:test_support",
+    "//components/sessions:session_id",
+  ]
+  deps = [
+    "//content/test:test_support",
+    "//net:test_support",
+    "//testing/gtest",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "autocomplete_action_predictor_table_unittest.cc",
+    "autocomplete_action_predictor_unittest.cc",
+    "loading_data_collector_unittest.cc",
+    "loading_predictor_config_unittest.cc",
+    "loading_predictor_tab_helper_unittest.cc",
+    "loading_predictor_unittest.cc",
+    "loading_stats_collector_unittest.cc",
+    "perform_network_context_prefetch_unittest.cc",
+    "prefetch_manager_unittest.cc",
+    "resource_prefetch_predictor_tables_unittest.cc",
+    "resource_prefetch_predictor_unittest.cc",
+  ]
+
+  deps = [
+    ":impl",
+    ":predictors",
+    ":test_support",
+    "//base/test:test_support",
+    "//chrome/browser/history",
+    "//chrome/browser/optimization_guide",
+    "//chrome/browser/optimization_guide:test_support",
+    "//chrome/browser/preloading",
+    "//chrome/browser/preloading:prefs",
+    "//chrome/browser/sessions",
+    "//chrome/common",
+    "//chrome/test:test_support",
+    "//components/no_state_prefetch/browser",
+    "//components/omnibox/browser",
+    "//components/omnibox/common",
+    "//components/optimization_guide/core",
+    "//components/optimization_guide/proto:optimization_guide_proto",
+    "//components/sessions",
+    "//components/ukm:test_support",
+    "//components/variations",
+    "//content/test:test_support",
+    "//mojo/public/cpp/bindings",
+    "//net:test_support",
+    "//services/metrics/public/cpp:ukm_builders",
+    "//services/network:test_support",
+    "//services/network/public/cpp",
+    "//services/network/public/mojom",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/blink/public/common:headers",
+  ]
+}
+
+if (!is_android) {
+  source_set("browser_tests") {
+    testonly = true
+    defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
+    sources = [ "loading_predictor_browsertest.cc" ]
+    deps = [
+      ":predictors",
+      ":test_support",
+      "//chrome/browser:browser_process",
+      "//chrome/browser/optimization_guide",
+      "//chrome/browser/ui",
+      "//chrome/common",
+      "//chrome/test:test_support",
+      "//chrome/test:test_support_ui",
+      "//components/no_state_prefetch/browser",
+      "//components/optimization_guide/core",
+      "//components/optimization_guide/proto:optimization_guide_proto",
+      "//components/page_load_metrics/browser:test_support",
+      "//content/test:test_support",
+      "//net:test_support",
+      "//services/network/public/cpp",
+      "//services/network/public/mojom",
+      "//third_party/blink/public/common:headers",
+    ]
+  }
+}
diff --git a/chrome/browser/predictors/lcp_critical_path_predictor/BUILD.gn b/chrome/browser/predictors/lcp_critical_path_predictor/BUILD.gn
new file mode 100644
index 0000000..0f8b1b4
--- /dev/null
+++ b/chrome/browser/predictors/lcp_critical_path_predictor/BUILD.gn
@@ -0,0 +1,82 @@
+# Copyright 2026 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/protobuf/proto_library.gni")
+
+assert(is_win || is_mac || is_linux || is_chromeos || is_android)
+
+proto_library("lcp_critical_path_predictor_proto") {
+  sources = [ "lcp_critical_path_predictor.proto" ]
+}
+
+source_set("headers") {
+  sources = [
+    "lcp_critical_path_predictor_util.h",
+    "prewarm_http_disk_cache_manager.h",
+  ]
+  public_deps = [
+    ":lcp_critical_path_predictor_proto",
+    "//chrome/browser/predictors:config",
+    "//chrome/browser/profiles:profile",
+    "//components/sqlite_proto",
+    "//net",
+    "//services/network/public/cpp",
+    "//services/network/public/mojom",
+    "//third_party/blink/public/mojom:mojom_platform_headers",
+    "//url",
+  ]
+}
+
+source_set("impl") {
+  sources = [
+    "lcp_critical_path_predictor_host.cc",
+    "lcp_critical_path_predictor_host.h",
+    "lcp_critical_path_predictor_util.cc",
+    "prewarm_http_disk_cache_manager.cc",
+  ]
+  public_deps = [ "//chrome/browser:browser_public_dependencies" ]
+  deps = [
+    ":headers",
+    "//chrome/browser/predictors",
+    "//net",
+    "//third_party/blink/public/common:headers",
+    "//url",
+  ]
+}
+
+source_set("test_support") {
+  testonly = true
+  sources = [
+    "lcp_critical_path_predictor_test_util.cc",
+    "lcp_critical_path_predictor_test_util.h",
+  ]
+  public_deps = [
+    ":lcp_critical_path_predictor_proto",
+    "//url",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "lcp_critical_path_predictor_util_unittest.cc",
+    "prewarm_http_disk_cache_manager_unittest.cc",
+  ]
+
+  deps = [
+    ":impl",
+    ":test_support",
+    "//base/test:test_support",
+    "//chrome/browser/predictors",
+    "//chrome/browser/predictors:test_support",
+    "//chrome/test:test_support",
+    "//content/test:test_support",
+    "//net",
+    "//services/network:test_support",
+    "//services/network/public/cpp",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/blink/public/common:headers",
+  ]
+}
diff --git a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util_unittest.cc b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util_unittest.cc
index 429b7fb..95fb78f 100644
--- a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util_unittest.cc
+++ b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h"
 
+#include <stdint.h>
+
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
@@ -20,8 +22,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
 
-using testing::StrictMock;
-
 namespace predictors {
 
 namespace {
@@ -1471,12 +1471,24 @@
   std::unique_ptr<LcppDataMap> lcpp_data_map_;
 };
 
-class LcppDataMapFeatures
-    : public LcppDataMapTest,
-      public testing::WithParamInterface<std::vector<base::test::FeatureRef>> {
+constexpr uint8_t kLcppFeatureSetDefault = 0;
+constexpr uint8_t kLcppFeatureSetInitiatorOrigin = 1 << 0;
+constexpr uint8_t kLcppFeatureSetMultipleKey = 1 << 1;
+constexpr uint8_t kLcppFeatureSetInitiatorOriginAndMultipleKey =
+    kLcppFeatureSetInitiatorOrigin | kLcppFeatureSetMultipleKey;
+
+class LcppDataMapFeatures : public LcppDataMapTest,
+                            public testing::WithParamInterface<uint8_t> {
  public:
   LcppDataMapFeatures() {
-    scoped_feature_list_.InitWithFeatures(GetParam(),
+    std::vector<base::test::FeatureRef> enabled_features;
+    if (GetParam() & kLcppFeatureSetInitiatorOrigin) {
+      enabled_features.push_back(blink::features::kLCPPInitiatorOrigin);
+    }
+    if (GetParam() & kLcppFeatureSetMultipleKey) {
+      enabled_features.push_back(blink::features::kLCPPMultipleKey);
+    }
+    scoped_feature_list_.InitWithFeatures(enabled_features,
                                           /*disabled_features=*/{});
     constexpr char kSlidingWindowSize[] = "5";
     constexpr char kMaxHistogramBuckets[] = "2";
@@ -1535,36 +1547,32 @@
       scoped_feature_list_for_sliding_window_and_buckets_;
 };
 
-auto& kLCPPInitiatorOrigin = blink::features::kLCPPInitiatorOrigin;
-auto& kLCPPMultipleKey = blink::features::kLCPPMultipleKey;
-const std::vector<base::test::FeatureRef> featureset1[] = {
-    {},
-    {kLCPPInitiatorOrigin},
-    {kLCPPMultipleKey},
-    {kLCPPInitiatorOrigin, kLCPPMultipleKey}};
 inline std::string CustomParamNameFunction(
     const testing::TestParamInfo<LcppDataMapFeatures::ParamType>& info) {
-  const auto& features = info.param;
-  if (features.empty()) {
+  const uint8_t feature_set = info.param;
+  if (feature_set == kLcppFeatureSetDefault) {
     return std::string("Default");
   }
   std::string name;
-  for (size_t i = 0; i < features.size(); i++) {
-    if (features[i] == kLCPPInitiatorOrigin) {
-      name += "InitiatorOrigin";
-    } else {
-      name += "MultipleKey";
-    }
-    if (i < features.size() - 1) {
+  if (feature_set & kLcppFeatureSetInitiatorOrigin) {
+    name += "InitiatorOrigin";
+  }
+  if (feature_set & kLcppFeatureSetMultipleKey) {
+    if (!name.empty()) {
       name += "_";
     }
+    name += "MultipleKey";
   }
   return name;
 }
-INSTANTIATE_TEST_SUITE_P(LcppFeatureSet1,
-                         LcppDataMapFeatures,
-                         testing::ValuesIn(featureset1),
-                         &CustomParamNameFunction);
+INSTANTIATE_TEST_SUITE_P(
+    LcppFeatureSet1,
+    LcppDataMapFeatures,
+    testing::Values(kLcppFeatureSetDefault,
+                    kLcppFeatureSetInitiatorOrigin,
+                    kLcppFeatureSetMultipleKey,
+                    kLcppFeatureSetInitiatorOriginAndMultipleKey),
+    &CustomParamNameFunction);
 
 TEST_P(LcppDataMapFeatures, Base) {
   LoadingPredictorConfig config;
@@ -1894,12 +1902,10 @@
 
 class LcppDataMapFeatures2 : public LcppDataMapFeatures {};
 
-const std::vector<base::test::FeatureRef> featureset2[] = {
-    {},
-    {kLCPPInitiatorOrigin}};
 INSTANTIATE_TEST_SUITE_P(LcppFeatureSet2,
                          LcppDataMapFeatures2,
-                         testing::ValuesIn(featureset2),
+                         testing::Values(kLcppFeatureSetDefault,
+                                         kLcppFeatureSetInitiatorOrigin),
                          &CustomParamNameFunction);
 
 TEST_P(LcppDataMapFeatures2, LcppLearnURL) {
@@ -1953,7 +1959,8 @@
          {{kLcppMultipleKeyType.name,
            kLcppMultipleKeyType.GetName(std::get<1>(GetParam()))}}}};
     if (std::get<0>(GetParam())) {
-      base::test::FeatureRefAndParams params = {kLCPPInitiatorOrigin, {}};
+      base::test::FeatureRefAndParams params = {
+          blink::features::kLCPPInitiatorOrigin, {}};
       enabled_features.push_back(params);
     }
     scoped_feature_list_.InitWithFeaturesAndParameters(
@@ -2073,7 +2080,8 @@
            kLcppMultipleKeyType.GetName(
                blink::features::LcppMultipleKeyTypes::kDefault)}}}};
     if (GetParam()) {
-      base::test::FeatureRefAndParams params = {kLCPPInitiatorOrigin, {}};
+      base::test::FeatureRefAndParams params = {
+          blink::features::kLCPPInitiatorOrigin, {}};
       enabled_features.push_back(params);
     }
     scoped_feature_list_.InitWithFeaturesAndParameters(
@@ -2145,7 +2153,8 @@
     std::vector<base::test::FeatureRefAndParams> enabled_features = {
         ScopedLcppKeyStatFeature::GetParam()};
     if (GetParam()) {
-      base::test::FeatureRefAndParams params = {kLCPPInitiatorOrigin, {}};
+      base::test::FeatureRefAndParams params = {
+          blink::features::kLCPPInitiatorOrigin, {}};
       enabled_features.push_back(params);
     }
     scoped_feature_list_.InitWithFeaturesAndParameters(
diff --git a/chrome/browser/predictors/loading_data_collector.cc b/chrome/browser/predictors/loading_data_collector.cc
index 7f7150c..785f266 100644
--- a/chrome/browser/predictors/loading_data_collector.cc
+++ b/chrome/browser/predictors/loading_data_collector.cc
@@ -10,7 +10,6 @@
 #include <string>
 #include <utility>
 
-#include "chrome/browser/browser_features.h"
 #include "chrome/browser/predictors/loading_stats_collector.h"
 #include "chrome/browser/predictors/predictors_features.h"
 #include "chrome/browser/predictors/resource_prefetch_predictor.h"
diff --git a/chrome/browser/predictors/network_hints_handler_impl.cc b/chrome/browser/predictors/network_hints_handler_impl.cc
index 492565c..4baec27 100644
--- a/chrome/browser/predictors/network_hints_handler_impl.cc
+++ b/chrome/browser/predictors/network_hints_handler_impl.cc
@@ -84,13 +84,13 @@
   if (!render_frame_host)
     return;
 
-  // TODO(crbug.com/447954811): pass the `network_restrictions_id` from the
-  // caller.
+  std::optional<base::UnguessableToken> network_restrictions_id =
+      render_frame_host->GetNetworkRestrictionsID();
   preconnect_manager_->StartPreconnectUrl(
       url.GetURL(), allow_credentials,
       GetPendingNetworkAnonymizationKey(render_frame_host),
       kNetworkHintsTrafficAnnotation, /*storage_partition_config=*/nullptr,
-      /*network_restrictions_id=*/std::nullopt,
+      network_restrictions_id,
       /*keepalive_config=*/std::nullopt, mojo::NullRemote());
 }
 
diff --git a/chrome/browser/preloading/prefetch/no_state_prefetch/BUILD.gn b/chrome/browser/preloading/prefetch/no_state_prefetch/BUILD.gn
index f4392ad..3bb7ecc2 100644
--- a/chrome/browser/preloading/prefetch/no_state_prefetch/BUILD.gn
+++ b/chrome/browser/preloading/prefetch/no_state_prefetch/BUILD.gn
@@ -40,6 +40,7 @@
     "//base",
     "//chrome/browser/content_settings:content_settings_factory",
     "//chrome/browser/history",
+    "//chrome/browser/predictors",
     "//chrome/browser/preloading:prefs",
     "//chrome/browser/profiles:profile",
     "//chrome/browser/sync:factories",
diff --git a/chrome/browser/profiles/BUILD.gn b/chrome/browser/profiles/BUILD.gn
index 8d31d32a..f22d9fd 100644
--- a/chrome/browser/profiles/BUILD.gn
+++ b/chrome/browser/profiles/BUILD.gn
@@ -322,6 +322,7 @@
     "//chrome/browser/permissions",
     "//chrome/browser/persisted_state_db",
     "//chrome/browser/plus_addresses",
+    "//chrome/browser/predictors",
     "//chrome/browser/prefs",
     "//chrome/browser/preloading",
     "//chrome/browser/preloading/prefetch/no_state_prefetch",
diff --git a/chrome/browser/resources/actor_overlay/BUILD.gn b/chrome/browser/resources/actor_overlay/BUILD.gn
index 3b953e8..897d99a 100644
--- a/chrome/browser/resources/actor_overlay/BUILD.gn
+++ b/chrome/browser/resources/actor_overlay/BUILD.gn
@@ -4,8 +4,6 @@
 
 import("//ui/webui/resources/tools/build_webui.gni")
 
-assert(!is_android)
-
 build_webui("build") {
   grd_prefix = "actor_overlay"
 
diff --git a/chrome/browser/resources/glic/glic_api/glic_api.ts b/chrome/browser/resources/glic/glic_api/glic_api.ts
index 3c646b29..3b16bcc 100644
--- a/chrome/browser/resources/glic/glic_api/glic_api.ts
+++ b/chrome/browser/resources/glic/glic_api/glic_api.ts
@@ -2038,6 +2038,8 @@
    * the current tab context.
    */
   isPending?: boolean;
+  /** The host's invocation source. */
+  invocationSource?: InvocationSource;
 }
 
 /**
@@ -2629,6 +2631,8 @@
   PDF_SUMMARIZE_BUTTON = 17,
   // From a navigation capture.
   NAVIGATION_CAPTURE = 18,
+  // Automatically opened for a PDF.
+  AUTO_OPENED_FOR_PDF = 19,
 }
 
 ///////////////////////////////////////////////
@@ -2727,6 +2731,8 @@
   TRUST_FIRST_ONBOARDING_ARM2 = 5,
   // Glic host supports sharing additional image context.
   SHARE_ADDITIONAL_IMAGE_CONTEXT = 6,
+  // Enables the PDF Zero State Web UI.
+  PDF_ZERO_STATE = 7,
 }
 
 ///////////////////////////////////////////////
diff --git a/chrome/browser/resources/glic/glic_api_impl/host/conversions.ts b/chrome/browser/resources/glic/glic_api_impl/host/conversions.ts
index 1722e89..fafce88 100644
--- a/chrome/browser/resources/glic/glic_api_impl/host/conversions.ts
+++ b/chrome/browser/resources/glic/glic_api_impl/host/conversions.ts
@@ -18,9 +18,9 @@
 import type {Url} from '//resources/mojo/url/mojom/url.mojom-webui.js';
 
 import type {PageMetadata as PageMetadataMojo} from '../../ai_page_content_metadata.mojom-webui.js';
-import type {AdditionalContext as AdditionalContextMojo, AdditionalContextPart as AdditionalContextPartMojo, AnnotatedPageData as AnnotatedPageDataMojo, CaptureRegionResult as CaptureRegionResultMojo, ContextData as ContextDataMojo, ConversationInfo as ConversationInfoMojo, FocusedTabData as FocusedTabDataMojo, FormFactor as FormFactorMojo, GetPinCandidatesOptions as GetPinCandidatesOptionsMojo, GetTabContextOptions as TabContextOptionsMojo, HostCapability as HostCapabilityMojo, InvokeOptions as InvokeOptionsMojo, PanelOpeningData as PanelOpeningDataMojo, PanelState as PanelStateMojo, PdfDocumentData as PdfDocumentDataMojo, PinTabsOptions as PinTabsOptionsMojo, Platform as PlatformMojo, Screenshot as ScreenshotMojo, TabContext as TabContextMojo, TabData as TabDataMojo, UnpinTabsOptions as UnpinTabsOptionsMojo, WebPageData as WebPageDataMojo} from '../../glic.mojom-webui.js';
+import type {AdditionalContext as AdditionalContextMojo, AdditionalContextPart as AdditionalContextPartMojo, AnnotatedPageData as AnnotatedPageDataMojo, CaptureRegionResult as CaptureRegionResultMojo, ContextData as ContextDataMojo, ConversationInfo as ConversationInfoMojo, FocusedTabData as FocusedTabDataMojo, FormFactor as FormFactorMojo, GetPinCandidatesOptions as GetPinCandidatesOptionsMojo, GetTabContextOptions as TabContextOptionsMojo, HostCapability as HostCapabilityMojo, InvokeOptions as InvokeOptionsMojo, PanelOpeningData as PanelOpeningDataMojo, PanelState as PanelStateMojo, PdfDocumentData as PdfDocumentDataMojo, PinTabsOptions as PinTabsOptionsMojo, Platform as PlatformMojo, Screenshot as ScreenshotMojo, TabContext as TabContextMojo, TabData as TabDataMojo, UnpinTabsOptions as UnpinTabsOptionsMojo, WebPageData as WebPageDataMojo, ZeroStateSuggestionsV2 as ZeroStateSuggestionsV2Mojo} from '../../glic.mojom-webui.js';
 import {MicrophoneStatus as MicrophoneStatusMojo, PinTrigger as PinTriggerMojo, UnpinTrigger as UnpinTriggerMojo, WebClientMode as WebClientModeMojo} from '../../glic.mojom-webui.js';
-import type {AdditionalContextSource, CaptureRegionResult, ConversationInfo, CredentialType, FeatureMode, FormFactor, GetPinCandidatesOptions, HostCapability, InvocationSource, PageMetadata, PanelOpeningData, PanelState, PinTabsOptions, PinTrigger, Platform, Screenshot, TabContextOptions, TaskOptions, UnpinTabsOptions, UnpinTrigger, WebPageData} from '../../glic_api/glic_api.js';
+import type {AdditionalContextSource, CaptureRegionResult, ConversationInfo, CredentialType, FeatureMode, FormFactor, GetPinCandidatesOptions, HostCapability, InvocationSource, PageMetadata, PanelOpeningData, PanelState, PinTabsOptions, PinTrigger, Platform, Screenshot, TabContextOptions, TaskOptions, UnpinTabsOptions, UnpinTrigger, WebPageData, ZeroStateSuggestionsV2} from '../../glic_api/glic_api.js';
 import {DEFAULT_INNER_TEXT_BYTES_LIMIT, DEFAULT_PDF_SIZE_LIMIT, MicrophoneStatus, WebClientMode} from '../../glic_api/glic_api.js';
 
 import type {ConfirmationRequestErrorReason as ConfirmationRequestErrorReasonMojo, CredentialType as CredentialTypeMojo, NavigationConfirmationRequest as NavigationConfirmationRequestMojo, NavigationConfirmationResponse as NavigationConfirmationResponseMojo, SelectAutofillSuggestionsDialogErrorReason as SelectAutofillSuggestionsDialogErrorReasonMojo, SelectAutofillSuggestionsDialogRequest as SelectAutofillSuggestionsDialogRequestMojo, SelectAutofillSuggestionsDialogResponse as SelectAutofillSuggestionsDialogResponseMojo, SelectCredentialDialogErrorReason as SelectCredentialDialogErrorReasonMojo, SelectCredentialDialogRequest as SelectCredentialDialogRequestMojo, SelectCredentialDialogResponse as SelectCredentialDialogResponseMojo, TaskOptions as TaskOptionsMojo, UserConfirmationDialogRequest as UserConfirmationDialogRequestMojo, UserConfirmationDialogResponse as UserConfirmationDialogResponseMojo, UserGrantedPermissionDuration as UserGrantedPermissionDurationMojo} from './../../actor_webui.mojom-webui.js';
@@ -657,6 +657,16 @@
   };
 }
 
+export function zeroStateSuggestionsToClient(
+    zeroStateSuggestions: ZeroStateSuggestionsV2Mojo): ZeroStateSuggestionsV2 {
+  return {
+    suggestions: zeroStateSuggestions.suggestions,
+    isPending: zeroStateSuggestions.isPending,
+    invocationSource: zeroStateSuggestions.invocationSource as number as
+        InvocationSource,
+  };
+}
+
 export function invokeOptionsToClient(
     options: InvokeOptionsMojo, extras: ResponseExtras): InvokeOptionsPrivate {
   return {
diff --git a/chrome/browser/resources/glic/glic_api_impl/host/host_from_client.ts b/chrome/browser/resources/glic/glic_api_impl/host/host_from_client.ts
index faa45a9c..053bb0ec 100644
--- a/chrome/browser/resources/glic/glic_api_impl/host/host_from_client.ts
+++ b/chrome/browser/resources/glic/glic_api_impl/host/host_from_client.ts
@@ -19,7 +19,7 @@
 import type {HostRequestTypes, RequestRequestType, RequestResponseType, ResumeActorTaskResultPrivate, RgbaImage, TabContextResultPrivate, TransferableException, WebClientInitialStatePrivate} from '../request_types.js';
 import {ErrorWithReasonImpl, exceptionFromTransferable} from '../request_types.js';
 
-import {bitmapN32ToRGBAImage, byteArrayFromClient, captureRegionResultToClient, conversationInfoFromClient, focusedTabDataToClient, formFactorToClient, getArrayBufferFromBigBuffer, getPinCandidatesOptionsFromClient, hostCapabilitiesToClient, idFromClient, idToClient, microphoneStatusToMojo, optionalFromClient, optionalToClient, panelStateToClient, pinTabsOptionsToMojo, platformToClient, resumeActorTaskResultToClient, tabContextOptionsFromClient, tabContextToClient, tabDataToClient, taskOptionsToMojo, timeDeltaFromClient, unpinTabsOptionsToMojo, urlFromClient, urlToClient, webClientModeToMojo} from './conversions.js';
+import {bitmapN32ToRGBAImage, byteArrayFromClient, captureRegionResultToClient, conversationInfoFromClient, focusedTabDataToClient, formFactorToClient, getArrayBufferFromBigBuffer, getPinCandidatesOptionsFromClient, hostCapabilitiesToClient, idFromClient, idToClient, microphoneStatusToMojo, optionalFromClient, optionalToClient, panelStateToClient, pinTabsOptionsToMojo, platformToClient, resumeActorTaskResultToClient, tabContextOptionsFromClient, tabContextToClient, tabDataToClient, taskOptionsToMojo, timeDeltaFromClient, unpinTabsOptionsToMojo, urlFromClient, urlToClient, webClientModeToMojo, zeroStateSuggestionsToClient} from './conversions.js';
 import type {GatedSender} from './gated_sender.js';
 import type {ApiHostEmbedder, GlicApiHost} from './glic_api_host.js';
 import {DetailedWebClientState} from './glic_api_host.js';
@@ -862,7 +862,7 @@
     if (!zeroStateData) {
       return {};
     } else {
-      return {suggestions: zeroStateData};
+      return {suggestions: zeroStateSuggestionsToClient(zeroStateData)};
     }
   }
   glicBrowserDropScrollToHighlight(): void {
diff --git a/chrome/browser/resources/glic/glic_api_impl/host/host_to_client.ts b/chrome/browser/resources/glic/glic_api_impl/host/host_to_client.ts
index 3fac6d19..03cccb5 100644
--- a/chrome/browser/resources/glic/glic_api_impl/host/host_to_client.ts
+++ b/chrome/browser/resources/glic/glic_api_impl/host/host_to_client.ts
@@ -13,7 +13,7 @@
 
 import type {NavigationConfirmationRequest as NavigationConfirmationRequestMojo, NavigationConfirmationResponse as NavigationConfirmationResponseMojo, SelectAutofillSuggestionsDialogRequest as SelectAutofillSuggestionsDialogRequestMojo, SelectAutofillSuggestionsDialogResponse as SelectAutofillSuggestionsDialogResponseMojo, SelectCredentialDialogRequest as SelectCredentialDialogRequestMojo, SelectCredentialDialogResponse as SelectCredentialDialogResponseMojo, UserConfirmationDialogRequest as UserConfirmationDialogRequestMojo, UserConfirmationDialogResponse as UserConfirmationDialogResponseMojo} from './../../actor_webui.mojom-webui.js';
 import {ResponseExtras} from './../post_message_transport.js';
-import {additionalContextToClient, focusedTabDataToClient, idToClient, invokeOptionsToClient, navigationConfirmationRequestToClient, navigationConfirmationResponseToMojo, optionalToClient, pageMetadataToClient, panelOpeningDataToClient, panelStateToClient, selectAutofillSuggestionsDialogRequestToClient, selectAutofillSuggestionsDialogResponseToMojo, selectCredentialDialogRequestToClient, selectCredentialDialogResponseToMojo, tabDataToClient, timeDeltaFromClient, userConfirmationDialogRequestToClient, userConfirmationDialogResponseToMojo, webClientModeToMojo} from './conversions.js';
+import {additionalContextToClient, focusedTabDataToClient, idToClient, invokeOptionsToClient, navigationConfirmationRequestToClient, navigationConfirmationResponseToMojo, optionalToClient, pageMetadataToClient, panelOpeningDataToClient, panelStateToClient, selectAutofillSuggestionsDialogRequestToClient, selectAutofillSuggestionsDialogResponseToMojo, selectCredentialDialogRequestToClient, selectCredentialDialogResponseToMojo, tabDataToClient, timeDeltaFromClient, userConfirmationDialogRequestToClient, userConfirmationDialogResponseToMojo, webClientModeToMojo, zeroStateSuggestionsToClient} from './conversions.js';
 import type {GatedSender} from './gated_sender.js';
 import type {ApiHostEmbedder, GlicApiHost} from './glic_api_host.js';
 import {PanelOpenState} from './types.js';
@@ -250,8 +250,10 @@
       suggestions: ZeroStateSuggestionsV2Mojo,
       options: ZeroStateSuggestionsOptionsMojo): void {
     this.sender.sendLatestWhenActive(
-        'glicWebClientZeroStateSuggestionsChanged',
-        {suggestions: suggestions, options: options});
+        'glicWebClientZeroStateSuggestionsChanged', {
+          suggestions: zeroStateSuggestionsToClient(suggestions),
+          options: options,
+        });
   }
 
   notifyActorTaskStateChanged(taskId: number, state: ActorTaskStateMojo): void {
diff --git a/chrome/browser/resources/new_tab_page/action_chips/action_chips.ts b/chrome/browser/resources/new_tab_page/action_chips/action_chips.ts
index b4b591f..a2b9636 100644
--- a/chrome/browser/resources/new_tab_page/action_chips/action_chips.ts
+++ b/chrome/browser/resources/new_tab_page/action_chips/action_chips.ts
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
 
-import type {ContextualUpload, TabUpload} from 'chrome://resources/cr_components/composebox/common.js';
+import type {TabUpload} from 'chrome://resources/cr_components/composebox/common.js';
 import {TabUploadOrigin} from 'chrome://resources/cr_components/composebox/common.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import type {PropertyValues} from 'chrome://resources/lit/v3_0/lit.rollup.js';
@@ -168,63 +168,25 @@
     }
   }
 
-  protected onCreateImageClick_(chip: ActionChip) {
-    recordClick(chip.suggestTemplateInfo.typeIcon);
-    this.onActionChipClick_(chip.suggestion, [], ToolMode.kImageGen);
-  }
-
-  protected onDeepDiveClick_(chip: ActionChip) {
-    recordClick(chip.suggestTemplateInfo.typeIcon);
-    const tab = chip.tab!;
-    const deepDiveTabInfo: TabUpload = {
-      tabId: tab.tabId,
-      url: tab.url,
-      title: tab.title,
-      delayUpload: this.delayTabUploads_,
-      origin: TabUploadOrigin.ACTION_CHIP,
-    };
-    this.onActionChipClick_(
-        chip.suggestion, [deepDiveTabInfo], ToolMode.kUnspecified);
-  }
-
-  protected onDeepSearchClick_(chip: ActionChip) {
-    recordClick(chip.suggestTemplateInfo.typeIcon);
-    this.onActionChipClick_(chip.suggestion, [], ToolMode.kDeepSearch);
-  }
-
-  protected onTabContextClick_(chip: ActionChip) {
-    recordClick(chip.suggestTemplateInfo.typeIcon);
-    const tab = chip.tab!;
-    const recentTabInfo: TabUpload = {
-      tabId: tab.tabId,
-      url: tab.url,
-      title: tab.title,
-      delayUpload: this.delayTabUploads_,
-      origin: TabUploadOrigin.ACTION_CHIP,
-    };
-    this.onActionChipClick_(
-        chip.suggestion, [recentTabInfo], ToolMode.kUnspecified);
-  }
-
   protected handleClick_(e: Event): void {
     const index = Number((e.currentTarget as HTMLElement).dataset['index']);
     const chip = this.actionChips_[index]!;
     switch (chip.suggestTemplateInfo.typeIcon) {
       case IconType.kBanana:
         this.handler.activateMetricsFunnel('CreateImageChip');
-        this.onCreateImageClick_(chip);
+        this.onActionChipClick_(chip, ToolMode.kImageGen);
         break;
       case IconType.kGlobeWithSearchLoop:
         this.handler.activateMetricsFunnel('DeepSearchChip');
-        this.onDeepSearchClick_(chip);
+        this.onActionChipClick_(chip, ToolMode.kDeepSearch);
         break;
       case IconType.kFavicon:
         this.handler.activateMetricsFunnel('RecentTabChip');
-        this.onTabContextClick_(chip);
+        this.onActionChipClick_(chip, ToolMode.kUnspecified);
         break;
       case IconType.kSubArrowRight:
         this.handler.activateMetricsFunnel('DeepDiveChip');
-        this.onDeepDiveClick_(chip);
+        this.onActionChipClick_(chip, ToolMode.kUnspecified);
         break;
       default:
         // Do nothing yet...
@@ -253,9 +215,23 @@
     return chip.tab ? this.getFaviconUrl_(chip.tab.url) : '';
   }
 
-  private onActionChipClick_(
-      query: string, contextFiles: ContextualUpload[], mode: ToolMode) {
-    this.fire('action-chip-click', {searchboxText: query, contextFiles, mode});
+  private onActionChipClick_(chip: ActionChip, mode: ToolMode) {
+    recordClick(chip.suggestTemplateInfo.typeIcon);
+    const contextFiles: TabUpload[] = [];
+    const tab = chip.tab;
+    if (tab) {
+      const tabInfo: TabUpload = {
+        tabId: tab.tabId,
+        url: tab.url,
+        title: tab.title,
+        delayUpload: this.delayTabUploads_,
+        origin: TabUploadOrigin.ACTION_CHIP,
+      };
+      contextFiles.push(tabInfo);
+    }
+    this.fire(
+        'action-chip-click',
+        {searchboxText: chip.suggestion, contextFiles, mode});
   }
 
   protected recentTabChipTitle_(chip: ActionChip) {
diff --git a/chrome/browser/resources/new_tab_page/lazy_load.ts b/chrome/browser/resources/new_tab_page/lazy_load.ts
index f23e51f4..5eeeebaa 100644
--- a/chrome/browser/resources/new_tab_page/lazy_load.ts
+++ b/chrome/browser/resources/new_tab_page/lazy_load.ts
@@ -26,6 +26,7 @@
 export {CustomizeButtonsElement} from 'chrome://new-tab-page/shared/customize_buttons/customize_buttons.js';
 export type {ComposeboxFile} from 'chrome://resources/cr_components/composebox/common.js';
 export {ComposeboxElement, VoiceSearchAction} from 'chrome://resources/cr_components/composebox/composebox.js';
+export {ComposeboxFileInputsElement} from 'chrome://resources/cr_components/composebox/composebox_file_inputs.js';
 export {ComposeboxProxyImpl} from 'chrome://resources/cr_components/composebox/composebox_proxy.js';
 export {ContextualEntrypointAndCarouselElement} from 'chrome://resources/cr_components/composebox/contextual_entrypoint_and_carousel.js';
 export {ErrorScrimElement} from 'chrome://resources/cr_components/composebox/error_scrim.js';
diff --git a/chrome/browser/resources/omnibox_popup/aim_app.css b/chrome/browser/resources/omnibox_popup/aim_app.css
index 41e4dd8d..75ee3d34 100644
--- a/chrome/browser/resources/omnibox_popup/aim_app.css
+++ b/chrome/browser/resources/omnibox_popup/aim_app.css
@@ -91,6 +91,10 @@
   top: 14px;
 }
 
+cr-composebox::part(text-container) {
+  height: 44px;
+}
+
 cr-composebox::part(voice-icon) {
   --cr-icon-button-fill-color: var(--cr-composebox-voice-icon-fill-color);
 }
diff --git a/chrome/browser/resources/omnibox_popup/app.ts b/chrome/browser/resources/omnibox_popup/app.ts
index 99f1bf9..640bdc0f 100644
--- a/chrome/browser/resources/omnibox_popup/app.ts
+++ b/chrome/browser/resources/omnibox_popup/app.ts
@@ -14,6 +14,7 @@
 import {SearchboxBrowserProxy} from '//resources/cr_components/searchbox/searchbox_browser_proxy.js';
 import type {SearchboxDropdownElement} from '//resources/cr_components/searchbox/searchbox_dropdown.js';
 import {kDefaultSelection} from '//resources/cr_components/searchbox/searchbox_match.js';
+import {getInstance as getA11yAnnouncer} from '//resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
 import {I18nMixinLit} from '//resources/cr_elements/i18n_mixin_lit.js';
 import {assertNotReached} from '//resources/js/assert.js';
 import {EventTracker} from '//resources/js/event_tracker.js';
@@ -35,6 +36,22 @@
 const canShowSecondarySideMediaQueryList =
     window.matchMedia('(min-width: 675px)');
 
+// Notifies an a11y announcer to read the aria-label for given element.
+function announceElementAriaLabel(element: HTMLElement) {
+  const message = element.getAttribute('aria-label');
+  if (message) {
+    // Note: ariaNotify is more efficient and appears to work more reliably, but
+    // support is not guaranteed in all browsers. Fall back on a11y announcer if
+    // the ariaNotify function is unavailable.
+    const ariaNotify = (element as any).ariaNotify;
+    if (ariaNotify) {
+      ariaNotify.call(element, message);
+    } else {
+      getA11yAnnouncer(element)?.announce(message);
+    }
+  }
+}
+
 // Not all selection states of the webui popup are supported on the native
 // browser side.
 function selectionIsNativelySupported(s: OmniboxPopupSelection): boolean {
@@ -370,6 +387,10 @@
     if (entrypoint) {
       entrypoint.hasPopupFocus = this.selection_.state ===
           SelectionLineState.kFocusedButtonContextEntrypoint;
+      if (entrypoint.hasPopupFocus) {
+        announceElementAriaLabel(
+            entrypoint.shadowRoot.querySelector('#entrypoint')!);
+      }
     }
   }
 
diff --git a/chrome/browser/resources/settings/glic_page/glic_subpage.html b/chrome/browser/resources/settings/glic_page/glic_subpage.html
index 83e837fb..596dfb3 100644
--- a/chrome/browser/resources/settings/glic_page/glic_subpage.html
+++ b/chrome/browser/resources/settings/glic_page/glic_subpage.html
@@ -90,6 +90,7 @@
           <cr-shortcut-input class="cr-padded-text shortcut-input"
               input-aria-label="$i18n{glicKeyboardShortcut}"
               edit-button-aria-label="$i18n{glicKeyboardShortcutEditLabel}"
+              clear-button-aria-label="$i18n{glicKeyboardShortcutClearLabel}"
               shortcut="[[registeredShortcut_]]"
               allow-ctrl-alt-shortcuts
               on-input-capture-change="onInputCaptureChange_"
@@ -116,7 +117,8 @@
         </div>
         <cr-shortcut-input class="cr-padded-text shortcut-input"
             input-aria-label="$i18n{glicNavigationShortcut}"
-              edit-button-aria-label="$i18n{glicNavigationShortcutEditLabel}"
+            edit-button-aria-label="$i18n{glicNavigationShortcutEditLabel}"
+            clear-button-aria-label="$i18n{glicNavigationShortcutClearLabel}"
             shortcut="[[registeredFocusToggleShortcut_]]"
             allow-ctrl-alt-shortcuts
             on-shortcut-updated="onFocusToggleShortcutUpdated_">
diff --git a/chrome/browser/resources/settings/glic_page/glic_subpage.ts b/chrome/browser/resources/settings/glic_page/glic_subpage.ts
index a2b6bde..01f974f 100644
--- a/chrome/browser/resources/settings/glic_page/glic_subpage.ts
+++ b/chrome/browser/resources/settings/glic_page/glic_subpage.ts
@@ -377,10 +377,10 @@
 
   private async onShortcutUpdated_(event: CustomEvent<string>) {
     this.shortcutInput_ = event.detail;
-    await this.browserProxy_.setGlicShortcut(this.shortcutInput_);
     if (this.removedShortcut_ === null) {
       this.removedShortcut_ = this.registeredShortcut_;
     }
+    await this.browserProxy_.setGlicShortcut(this.shortcutInput_);
     this.registeredShortcut_ = await this.browserProxy_.getGlicShortcut();
     // Records true if the shortcut string is defined and not empty.
     this.metricsBrowserProxy_.recordBooleanHistogram(
diff --git a/chrome/browser/resources/settings/privacy_page/security/security_page_v2.html b/chrome/browser/resources/settings/privacy_page/security/security_page_v2.html
index 35f75f5..1342bd9 100644
--- a/chrome/browser/resources/settings/privacy_page/security/security_page_v2.html
+++ b/chrome/browser/resources/settings/privacy_page/security/security_page_v2.html
@@ -180,10 +180,17 @@
     display: flex;
     justify-content: space-between;
     padding-bottom: var(--cr-section-vertical-padding);
-    padding-inline-end: 16px;
-    padding-inline-start: 20px;
+    padding-inline: var(--cr-section-padding);
     padding-top: var(--cr-section-vertical-padding);
   }
+
+  #javascriptGuardrailsRow [slot=collapse] {
+    padding: 0;
+  }
+
+  #javascriptGuardrailsRadioGroup {
+    padding-inline: var(--cr-section-padding);
+  }
 </style>
 <settings-subpage page-title="$i18n{securityPageTitle}"
     learn-more-url="$i18n{safeBrowsingHelpCenterURL}"
diff --git a/chrome/browser/resources/skills/skills_dialog.css b/chrome/browser/resources/skills/skills_dialog.css
index 1a0e63c..db78688d 100644
--- a/chrome/browser/resources/skills/skills_dialog.css
+++ b/chrome/browser/resources/skills/skills_dialog.css
@@ -10,17 +10,27 @@
  * #include=cr-shared-style-lit
  * #css_wrapper_metadata_end */
 
-.dialog-container {
-  background-color: var(--color-sys-surface);
-  display: grid;
-  gap: 16px;
-  overflow: hidden;
-  padding: 12px;
+cr-dialog {
+  --cr-dialog-background-color: var(--color-sys-surface);
+  --cr-dialog-border-radius: 12px;
+  --cr-dialog-shadow: none;
+  --cr-dialog-width: 100%;
 }
 
-.header-container {
+cr-dialog::part(dialog) {
+  box-shadow: none;
+}
+
+/* Needed to prevent the dialog body from being scrollable. */
+cr-dialog::part(wrapper) {
+  height: auto;
+  max-height: none;
+}
+
+[slot='title'] {
   display: grid;
   gap: 4px;
+  padding: 20px 20px 16px 20px;
 }
 
 h1 {
@@ -39,7 +49,16 @@
   margin: 0;
 }
 
+[slot='body'] {
+  display: flex;
+  flex-direction: column;
+  gap: 16px;
+  padding: 0 20px 16px 20px;
+}
+
 .form-group {
+  display: flex;
+  flex-direction: column;
   gap: 16px;
 }
 
@@ -48,6 +67,7 @@
 }
 
 cr-input {
+  --cr-input-error-display: none;
   --cr-input-focus-outline-color: var(--cr-focus-outline-color);
   --cr-input-font-size: 12px;
   --cr-input-hover-background-color: var(--color-sys-surface-variant);
@@ -236,29 +256,6 @@
   background-color: var(--cr-hover-background-color);
 }
 
-#accountInfo {
-  background-color: var(--color-sys-base-container);
-  border-radius: 8px;
-  display: flex;
-  flex-direction: column;
-  gap: 4px;
-  padding: 12px 16px;
-}
-
-#accountLabel {
-  color: var(--color-sys-on-surface);
-  font-size: 12px;
-  font-weight: 500;
-  line-height: 16px;
-}
-
-#accountEmail {
-  color: var(--color-sys-on-surface-subtle);
-  font-size: 12px;
-  font-weight: 400;
-  line-height: 16px;
-}
-
 .error-message {
   font-size: 11px;
   line-height: 16px;
@@ -305,3 +302,22 @@
   --iron-icon-width: 16px;
   --iron-icon-height: 16px;
 }
+
+[slot='footer'] {
+  background-color: var(--color-sys-neutral-container);
+  border-top: 1px solid var(--color-sys-neutral-outline);
+  box-sizing: border-box;
+  font-size: 12px;
+  font-weight: 400;
+  gap: 4px;
+  line-height: 18px;
+  padding: 15px 20px 20px 20px;
+}
+
+#accountLabel {
+  color: var(--color-sys-on-surface);
+}
+
+#accountEmail {
+  color: var(--color-sys-primary);
+}
diff --git a/chrome/browser/resources/skills/skills_dialog.html b/chrome/browser/resources/skills/skills_dialog.html
index ae970b2..d6f446b 100644
--- a/chrome/browser/resources/skills/skills_dialog.html
+++ b/chrome/browser/resources/skills/skills_dialog.html
@@ -6,6 +6,11 @@
   <meta charset="utf-8">
   <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
   <link rel="stylesheet" href="chrome://theme/colors.css?sets=ui,chrome">
+  <style>
+    body {
+      margin: 0;
+    }
+  </style>
 </head>
 <body>
   <script src="skills_dialog_app.js" type="module"></script>
diff --git a/chrome/browser/resources/skills/skills_dialog_app.html.ts b/chrome/browser/resources/skills/skills_dialog_app.html.ts
index a6fd759c..a158d9d 100644
--- a/chrome/browser/resources/skills/skills_dialog_app.html.ts
+++ b/chrome/browser/resources/skills/skills_dialog_app.html.ts
@@ -11,104 +11,116 @@
   // clang-format off
   return html`<!--_html_template_start_-->
 ${this.shouldShowErrorPage_ ? html`<error-page></error-page>` : html`
-  <div class="dialog-container">
-    <div class="header-container">
+  <cr-dialog id="dialog" show-on-attach hide-backdrop @close="${this.cancel_}">
+    <div slot="title">
       <h1 id="header">${this.dialogTitle_}</h1>
       <p class="description">$i18n{skillDescription}</p>
     </div>
-    <div class="form-group">
-    <div id="nameWrapper">
-      <div id="nameLabel" class="cr-form-field-label" aria-hidden="true">$i18n{name}
+    <div slot="body">
+        <div id="nameWrapper">
+          <div id="nameLabel" class="cr-form-field-label" aria-hidden="true">$i18n{name}
+          </div>
+          ${this.isAutoGenerationLoading_ ? html`
+              <div id="nameLoaderContainer">
+                <cr-loading-gradient>
+                  <svg width="100%" height="38">
+                    <clipPath>
+                      <circle cx="20" cy="19" r="8"></circle>
+                      <rect x="40" y="13" width="100%" height="12" rx="4"></rect>
+                    </clipPath>
+                  </svg>
+                </cr-loading-gradient>
+              </div>
+            `
+            : html`
+            <cr-input class="stroked" id="nameText" type="text"
+                placeholder="$i18n{namePlaceholder}" .value="${this.skill_.name}"
+                @value-changed="${this.onNameChanged_}" aria-labelledby="nameLabel">
+              <div class="emoji-prefix-container" slot="inline-prefix">
+                <cr-icon id="emojiZeroStateIcon" icon="skills:add-reaction"
+                    ?hidden="${this.skill_.icon}" aria-hidden="true">
+                </cr-icon>
+                <input id="emojiTrigger" class="emoji-trigger" type="text"
+                  .value="${this.skill_.icon}" @click="${this.onEmojiBtnClick_}"
+                  @input="${this.onEmojiChanged_}" @keydown="${this.onEmojiKeyDown_}"
+                  title="$i18n{chooseIcon}" aria-label="$i18n{chooseIcon}">
+              </div>
+            </cr-input>
+            `}
+        </div>
+        <div id="instructionsWrapper">
+          <div id="instructionsLabel" class="cr-form-field-label"
+              aria-hidden="true">
+            $i18n{instructions}
+          </div>
+          <div id="textareaWrapper" ?error="${this.hasRefineError_}"
+              ?loading="${this.isRefineLoading_}">
+            ${this.isRefineLoading_ ? html`
+              <cr-loading-gradient id="instructionsLoader">
+                <svg width="100%" height="90">
+                  <clipPath>
+                    <rect x="10" y="14" width="90%" height="12" rx="4"></rect>
+                    <rect x="10" y="38" width="90%" height="12" rx="4"></rect>
+                    <rect x="10" y="62" width="60%" height="12" rx="4"></rect>
+                  </clipPath>
+                </svg>
+              </cr-loading-gradient>
+            ` : html`
+              <textarea id="instructionsText"
+                  aria-labelledby="instructionsLabel"
+                  maxlength="${MAX_PROMPT_CHAR_COUNT}"
+                  placeholder="$i18n{instructionsPlaceholder}"
+                  .value="${this.skill_.prompt}"
+                  @input="${this.onInstructionsInput_}">
+              </textarea>
+            `}
+            <div class="textarea-actions">
+              <cr-icon-button id="iconUndo" iron-icon="skills:undo"
+                  class="refine-icon" title="$i18n{undo}"
+                  aria-label="$i18n{undo}" ?disabled="${this.isUndoDisabled_()}"
+                  @click="${this.onUndoClick_}">
+              </cr-icon-button>
+              <cr-icon-button id="iconRedo" iron-icon="skills:redo"
+                  class="refine-icon" title="$i18n{redo}"
+                  aria-label="$i18n{redo}" ?disabled="${this.isRedoDisabled_()}"
+                  @click="${this.onRedoClick_}">
+              </cr-icon-button>
+              <cr-icon-button id="iconRefine" iron-icon="skills:refine"
+                  class="refine-icon" title="$i18n{refine}"
+                  aria-label="$i18n{refine}"
+                  ?disabled="${this.isRefineDisabled_()}"
+                  @click="${this.onRefineClick_}">
+              </cr-icon-button>
+            </div>
+          </div>
+          <div id="refineErrorMessage" class="error-message"
+              ?hidden="${!this.hasRefineError_}">
+                $i18n{refineError}
+          </div>
+        </div>
+      <div id="saveErrorContainer" ?hidden="${!this.hasSaveError_}">
+        <cr-icon icon="cr:error-outline" class="icon-error"></cr-icon>
+        <div id="saveErrorMessage" class="error-message">$i18n{saveError}</div>
       </div>
-      ${this.isAutoGenerationLoading_ ? html`
-          <div id="nameLoaderContainer">
-            <cr-loading-gradient>
-              <svg width="100%" height="38">
-                <clipPath>
-                  <circle cx="20" cy="19" r="8"></circle>
-                  <rect x="40" y="13" width="100%" height="12" rx="4"></rect>
-                </clipPath>
-              </svg>
-            </cr-loading-gradient>
-          </div>
-        `
-        : html`
-        <cr-input class="stroked" id="nameText" type="text"
-            placeholder="$i18n{namePlaceholder}" .value="${this.skill_.name}"
-            @value-changed="${this.onNameChanged_}" aria-labelledby="nameLabel">
-          <div class="emoji-prefix-container" slot="inline-prefix">
-            <cr-icon id="emojiZeroStateIcon" icon="skills:add-reaction"
-                ?hidden="${this.skill_.icon}" aria-hidden="true">
-            </cr-icon>
-            <input id="emojiTrigger" class="emoji-trigger" type="text"
-              .value="${this.skill_.icon}" @click="${this.onEmojiBtnClick_}"
-              @input="${this.onEmojiChanged_}" @keydown="${this.onEmojiKeyDown_}"
-              title="$i18n{chooseIcon}" aria-label="$i18n{chooseIcon}">
-          </div>
-        </cr-input>
-        `}
-    </div>
-    <div id="instructionsLabel" class="cr-form-field-label" aria-hidden="true">
-      $i18n{instructions}
-    </div>
-    <div id="textareaWrapper" ?error="${this.hasRefineError_}"
-         ?loading="${this.isRefineLoading_}">
-      ${this.isRefineLoading_ ? html`
-        <cr-loading-gradient id="instructionsLoader">
-          <svg width="100%" height="90">
-            <clipPath>
-              <rect x="10" y="14" width="90%" height="12" rx="4"></rect>
-              <rect x="10" y="38" width="90%" height="12" rx="4"></rect>
-              <rect x="10" y="62" width="60%" height="12" rx="4"></rect>
-            </clipPath>
-          </svg>
-        </cr-loading-gradient>
-      ` : html`
-        <textarea id="instructionsText" aria-labelledby="instructionsLabel"
-            maxlength="${MAX_PROMPT_CHAR_COUNT}"
-            placeholder="$i18n{instructionsPlaceholder}"
-            .value="${this.skill_.prompt}"
-            @input="${this.onInstructionsInput_}">
-        </textarea>
-      `}
-      <div class="textarea-actions">
-        <cr-icon-button id="iconUndo" iron-icon="skills:undo"
-            class="refine-icon" title="$i18n{undo}" aria-label="$i18n{undo}"
-            ?disabled="${this.isUndoDisabled_()}" @click="${this.onUndoClick_}">
-        </cr-icon-button>
-        <cr-icon-button id="iconRedo" iron-icon="skills:redo"
-            class="refine-icon" title="$i18n{redo}" aria-label="$i18n{redo}"
-            ?disabled="${this.isRedoDisabled_()}" @click="${this.onRedoClick_}">
-        </cr-icon-button>
-        <cr-icon-button id="iconRefine" iron-icon="skills:refine"
-            class="refine-icon" title="$i18n{refine}" aria-label="$i18n{refine}"
-            ?disabled="${this.isRefineDisabled_()}"
-            @click="${this.onRefineClick_}">
-        </cr-icon-button>
+      <div class="buttons-group">
+        <cr-button id="cancelButton" class="cancel-button"
+            @click="${this.cancel_}">
+          $i18n{cancel}
+        </cr-button>
+        <cr-button  id="saveButton" class="action-button"
+            ?disabled="${this.isSaveButtonDisabled}"
+            @click="${this.submitSkill_}">
+          $i18n{save}
+        </cr-button>
       </div>
     </div>
-    <div id="refineErrorMessage" class="error-message"
-        ?hidden="${!this.hasRefineError_}">
-          $i18n{refineError}
+    <div slot="footer">
+      <div id="accountInfo">
+        <span id="accountLabel">$i18n{accountInfo}</span>
+        <span id="accountEmail">${this.signedInEmail_}</span>
+      </div>
     </div>
-  </div>
-  <div id="accountInfo">
-    <div id="accountLabel">$i18n{accountInfo}</div>
-    <div id="accountEmail">${this.signedInEmail_}</div>
-  </div>
-  <div id="saveErrorContainer" ?hidden="${!this.hasSaveError_}">
-    <cr-icon icon="cr:error-outline" class="icon-error"></cr-icon>
-    <div id="saveErrorMessage" class="error-message">$i18n{saveError}</div>
-  </div>
-  <div class="buttons-group">
-    <cr-button id="cancelButton" class="cancel-button" @click="${this.cancel_}">
-        $i18n{cancel}
-    </cr-button>
-    <cr-button id="saveButton" class="action-button"
-        ?disabled="${this.isSaveButtonDisabled}" @click="${this.submitSkill_}">
-        $i18n{save}
-    </cr-button>
-  </div>
+  </cr-dialog>
 `}
 <!--_html_template_end_-->`;
   // clang-format on
diff --git a/chrome/browser/resources/skills/skills_dialog_app.ts b/chrome/browser/resources/skills/skills_dialog_app.ts
index deeff36..a5a9e6b 100644
--- a/chrome/browser/resources/skills/skills_dialog_app.ts
+++ b/chrome/browser/resources/skills/skills_dialog_app.ts
@@ -4,9 +4,11 @@
 
 import '/strings.m.js';
 import 'chrome://resources/cr_elements/cr_button/cr_button.js';
+import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
 import 'chrome://resources/cr_elements/cr_icon/cr_icon.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
 import 'chrome://resources/cr_elements/cr_input/cr_input.js';
+import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
 import 'chrome://resources/cr_elements/cr_textarea/cr_textarea.js';
 import 'chrome://resources/cr_elements/cr_loading_gradient/cr_loading_gradient.js';
 import 'chrome://resources/cr_elements/icons.html.js';
@@ -15,6 +17,7 @@
 
 import {ColorChangeUpdater} from 'chrome://resources/cr_components/color_change_listener/colors_css_updater.js';
 import type {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
+import type {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
 import type {CrIconElement} from 'chrome://resources/cr_elements/cr_icon/cr_icon.js';
 import type {CrIconButtonElement} from 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
 import type {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.js';
@@ -57,19 +60,20 @@
   $: {
     accountEmail: HTMLElement,
     cancelButton: HTMLElement,
+    dialog: CrDialogElement,
     emojiTrigger: HTMLInputElement,
-    refineErrorMessage: HTMLElement,
+    emojiZeroStateIcon: CrIconElement,
     header: HTMLElement,
     iconRedo: CrIconButtonElement,
     iconRefine: CrIconButtonElement,
     iconUndo: CrIconButtonElement,
     instructionsText: HTMLTextAreaElement,
-    nameText: CrInputElement,
-    saveButton: CrButtonElement,
-    textareaWrapper: HTMLElement,
     nameLoaderContainer: HTMLElement,
+    nameText: CrInputElement,
+    refineErrorMessage: HTMLElement,
+    saveButton: CrButtonElement,
     saveErrorContainer: HTMLElement,
-    emojiZeroStateIcon: CrIconElement,
+    textareaWrapper: HTMLElement,
   };
 }
 
@@ -129,7 +133,8 @@
   private originalPrompt_: string = '';
   private refinedPrompt_: string = '';
 
-  private resizeObserver_: ResizeObserver|null = null;
+  private textareaResizeObserver_: ResizeObserver|null = null;
+  private dialogResizeObserver_: ResizeObserver|null = null;
 
   protected get isSaveButtonDisabled() {
     return !this.skill_.name || !this.skill_.prompt ||
@@ -162,22 +167,36 @@
           this.signedInEmail_ = email;
         });
     if (window.ResizeObserver) {
-      this.resizeObserver_ = new ResizeObserver(() => {
+      this.textareaResizeObserver_ = new ResizeObserver(() => {
         this.checkTextareaOverflow_();
       });
+
+      // Need to explicitly observe the native dialog element because cr-dialog
+      // always has size 0x0, so does not trigger child size changes required to
+      // expand the dialog.
+      this.dialogResizeObserver_ = new ResizeObserver(() => {
+        const dialog = this.$.dialog?.getNative();
+        if (dialog) {
+          document.body.style.height = `${dialog.offsetHeight}px`;
+        }
+      });
     }
   }
 
-  private disconnectResizeObserver_() {
-    if (this.resizeObserver_) {
-      this.resizeObserver_.disconnect();
-      this.resizeObserver_ = null;
+  private disconnectTextareaResizeObserver_() {
+    if (this.textareaResizeObserver_) {
+      this.textareaResizeObserver_.disconnect();
+      this.textareaResizeObserver_ = null;
     }
   }
 
   override disconnectedCallback() {
     super.disconnectedCallback();
-    this.disconnectResizeObserver_();
+    this.disconnectTextareaResizeObserver_();
+    if (this.dialogResizeObserver_) {
+      this.dialogResizeObserver_.disconnect();
+      this.dialogResizeObserver_ = null;
+    }
   }
 
   override updated(changedProperties: PropertyValues) {
@@ -188,19 +207,23 @@
     if (changedProperties.has('isRefineLoading_') && this.isRefineLoading_) {
       // Wait for the DOM to be fully updated.
       this.updateComplete.then(() => {
-        this.disconnectResizeObserver_();
+        this.disconnectTextareaResizeObserver_();
       });
     }
+
+    if (this.dialogResizeObserver_ && this.$.dialog) {
+      this.dialogResizeObserver_.observe(this.$.dialog.getNative());
+    }
   }
 
-  private attachResizeObserver_() {
+  private attachTextareaResizeObserver_() {
     const textarea = this.instructionsTextarea_;
-    this.disconnectResizeObserver_();
-    this.resizeObserver_ = new ResizeObserver(() => {
+    this.disconnectTextareaResizeObserver_();
+    this.textareaResizeObserver_ = new ResizeObserver(() => {
       this.checkTextareaOverflow_();
     });
     // Observe the current textarea
-    this.resizeObserver_.observe(textarea);
+    this.textareaResizeObserver_.observe(textarea);
     textarea.onscroll = () => this.checkTextareaOverflow_();
   }
 
@@ -361,7 +384,7 @@
         .finally(() => {
           this.isRefineLoading_ = false;
           this.updateComplete.then(() => {
-            this.attachResizeObserver_();
+            this.attachTextareaResizeObserver_();
             this.checkTextareaOverflow_();
             this.instructionsTextarea_.focus();
           });
@@ -392,7 +415,7 @@
         });
   }
 
-  /** Click listener for the cancel button. */
+  /** Click listener for the cancel button and closing dialog. */
   protected cancel_(e: Event) {
     e.preventDefault();
     SkillsDialogBrowserProxy.getInstance().handler.closeDialog();
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn
index 8f2c2cd..fb2c8d7 100644
--- a/chrome/browser/safe_browsing/BUILD.gn
+++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -462,6 +462,7 @@
           "incident_reporting/module_integrity_verifier_win.h",
           "incident_reporting/platform_state_store_win.cc",
         ]
+        deps += [ "//chrome/browser/install_verification" ]
       }
 
       deps += [
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
index bcb64c4..25f7d351 100644
--- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
+++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
@@ -492,7 +492,8 @@
       /* delay_opening_file */ false,
       base::BindOnce(&DeepScanningRequest::OnScanComplete,
                      weak_ptr_factory_.GetWeakPtr(), metadata_->GetFullPath()),
-      base::DoNothing(), metadata_->IsObfuscated());
+      base::DoNothing(), metadata_->IsObfuscated(),
+      /* force_sync_hash_computation */ false);
 
   request->set_filename(metadata_->GetTargetFilePath().AsUTF8Unsafe());
 
diff --git a/chrome/browser/search_integrity/search_integrity_factory.cc b/chrome/browser/search_integrity/search_integrity_factory.cc
index 0ef48c1..94366df 100644
--- a/chrome/browser/search_integrity/search_integrity_factory.cc
+++ b/chrome/browser/search_integrity/search_integrity_factory.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/search_integrity/search_integrity_factory.h"
 
+#include <memory>
+
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/search_integrity/search_integrity.h"
diff --git a/chrome/browser/search_integrity/search_integrity_factory.h b/chrome/browser/search_integrity/search_integrity_factory.h
index cec98c1..f529202 100644
--- a/chrome/browser/search_integrity/search_integrity_factory.h
+++ b/chrome/browser/search_integrity/search_integrity_factory.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_SEARCH_INTEGRITY_SEARCH_INTEGRITY_FACTORY_H_
 #define CHROME_BROWSER_SEARCH_INTEGRITY_SEARCH_INTEGRITY_FACTORY_H_
 
+#include <memory>
+
 #include "base/no_destructor.h"
 #include "chrome/browser/profiles/profile_keyed_service_factory.h"
 
diff --git a/chrome/browser/segmentation_platform/segmentation_platform_service_factory_unittest.cc b/chrome/browser/segmentation_platform/segmentation_platform_service_factory_unittest.cc
index 80a7222..f583411 100644
--- a/chrome/browser/segmentation_platform/segmentation_platform_service_factory_unittest.cc
+++ b/chrome/browser/segmentation_platform/segmentation_platform_service_factory_unittest.cc
@@ -717,6 +717,8 @@
       kSigninTipShown, processing::ProcessedValue::FromFloat(1));
   input_context->metadata_args.emplace(
       kCreateTabGroupsTipShown, processing::ProcessedValue::FromFloat(1));
+  input_context->metadata_args.emplace(
+      kCustomizeMVTTipShown, processing::ProcessedValue::FromFloat(1));
 
   ExpectGetClassificationResult(
       segmentation_platform::kTipsNotificationsRankerKey, prediction_options,
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc
index 9f453d04..5a9c2ce9 100644
--- a/chrome/browser/sessions/session_restore_browsertest.cc
+++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -3193,9 +3193,9 @@
     base::FilePath user_data_dir;
     EXPECT_TRUE(base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
     base::FilePath sessions_dir =
-        user_data_dir.AppendASCII(TestingProfile::kTestUserProfileDir);
-    if (!base::DeletePathRecursively(
-            sessions_dir.Append(sessions::kSessionsDirectory))) {
+        user_data_dir.AppendASCII(TestingProfile::kTestUserProfileDir)
+            .Append(sessions::kSessionsDirectory);
+    if (!base::DeletePathRecursively(sessions_dir)) {
       ADD_FAILURE() << "Unable to delete sessions directory";
       return false;
     }
@@ -3203,8 +3203,7 @@
       ADD_FAILURE() << "Unable to create sessions directory";
       return false;
     }
-    base::FilePath session_file_path = sessions_dir.Append(
-        base::FilePath(sessions::kLegacyCurrentSessionFileName));
+    base::FilePath session_file_path = sessions_dir.AppendUTF8("Session_1234");
     base::FilePath data_dir;
     if (!base::PathService::Get(chrome::DIR_TEST_DATA, &data_dir)) {
       ADD_FAILURE() << "Unable to get data dir";
diff --git a/chrome/browser/sessions/session_service_base.cc b/chrome/browser/sessions/session_service_base.cc
index 4860fd6..a3006e47 100644
--- a/chrome/browser/sessions/session_service_base.cc
+++ b/chrome/browser/sessions/session_service_base.cc
@@ -155,8 +155,8 @@
   // Covert SessionServiceType to backend CSM::SessionType enum.
   sessions::CommandStorageManager::SessionType backend_type =
       type == SessionServiceType::kSessionRestore
-          ? sessions::CommandStorageManager::kSessionRestore
-          : sessions::CommandStorageManager::kAppRestore;
+          ? sessions::CommandStorageManager::SessionType::kSessionRestore
+          : sessions::CommandStorageManager::SessionType::kAppRestore;
 
   command_storage_manager_ = std::make_unique<sessions::CommandStorageManager>(
       backend_type, profile->GetPath(), this,
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidCustomActionProvider.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidCustomActionProvider.java
index c4ea07bd..81291db 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidCustomActionProvider.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidCustomActionProvider.java
@@ -9,8 +9,6 @@
 import android.app.Activity;
 import android.content.ClipData;
 import android.content.ClipDescription;
-import android.content.ClipboardManager;
-import android.content.Context;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Build;
@@ -41,7 +39,6 @@
 import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.ui.base.Clipboard;
 import org.chromium.ui.base.WindowAndroid;
-import org.chromium.ui.widget.Toast;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -217,13 +214,10 @@
                             assert mLinkToTextCoordinator != null;
                             ShareParams textShareParams =
                                     mLinkToTextCoordinator.getShareParams(LinkToggleState.NO_LINK);
-                            ClipboardManager clipboard =
-                                    (ClipboardManager)
-                                            mActivity.getSystemService(Context.CLIPBOARD_SERVICE);
-                            clipboard.setPrimaryClip(
-                                    ClipData.newPlainText(
+                            Clipboard.getInstance()
+                                    .setText(
                                             textShareParams.getTitle(),
-                                            textShareParams.getTextAndUrl()));
+                                            assertNonNull(textShareParams.getTextAndUrl()));
                         })
                 .build();
     }
@@ -238,25 +232,19 @@
                             String linkUrl = mShareParams.getUrl();
                             Uri imageUri = mShareParams.getImageUriToShare();
                             if (imageUri != null) {
-                                // This call stores the URL in the cache image provider.
-                                Clipboard.getInstance().setImageUri(imageUri);
-
-                                ClipboardManager clipboard =
-                                        (ClipboardManager)
-                                                mActivity.getSystemService(
-                                                        Context.CLIPBOARD_SERVICE);
-                                ClipData clip =
+                                String mimeType = mShareParams.getFileContentType();
+                                assert mimeType != null;
+                                ClipData clipData =
                                         new ClipData(
                                                 "imageLink",
                                                 new String[] {
-                                                    mShareParams.getFileContentType(),
-                                                    ClipDescription.MIMETYPE_TEXT_PLAIN
+                                                    mimeType, ClipDescription.MIMETYPE_TEXT_PLAIN
                                                 },
                                                 new ClipData.Item(
                                                         linkUrl, /* intent= */ null, imageUri));
-                                clipboard.setPrimaryClip(clip);
-                                Toast.makeText(mActivity, R.string.image_copied, Toast.LENGTH_SHORT)
-                                        .show();
+                                Clipboard.getInstance()
+                                        .setImageUri(
+                                                imageUri, clipData, /* notifyOnSuccess= */ true);
                             }
                         })
                 .build();
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidShareSheetControllerUnitTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidShareSheetControllerUnitTest.java
index 5c5de51..95876e3 100644
--- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidShareSheetControllerUnitTest.java
+++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidShareSheetControllerUnitTest.java
@@ -51,9 +51,6 @@
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.DeviceInfo;
-import org.chromium.base.task.TaskTraits;
-import org.chromium.base.task.test.ShadowPostTask;
-import org.chromium.base.task.test.ShadowPostTask.TestImpl;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.RobolectricUtil;
 import org.chromium.base.test.util.CallbackHelper;
@@ -95,9 +92,7 @@
 
 /** Test for {@link AndroidShareSheetController} and {@link AndroidCustomActionProvider}. */
 @RunWith(BaseRobolectricTestRunner.class)
-@Config(
-        sdk = 34,
-        shadows = {ShadowPostTask.class})
+@Config(sdk = 34)
 public class AndroidShareSheetControllerUnitTest {
     private static final String SELECTOR_FOR_LINK_TO_TEXT = "selector";
 
@@ -160,15 +155,6 @@
         doAnswer(invocation -> new GURL(invocation.getArgument(0)))
                 .when(mMockDomDistillerUrlUtilsJni)
                 .getOriginalUrlFromDistillerUrl(anyString());
-        // Setup shadow post task for clipboard actions.
-        ShadowPostTask.setTestImpl(
-                new TestImpl() {
-                    @Override
-                    public void postDelayedTask(
-                            @TaskTraits int taskTraits, Runnable task, long delay) {
-                        task.run();
-                    }
-                });
 
         doReturn(true).when(mTabGroupSharingController).isAvailableForTab(any());
 
@@ -207,7 +193,6 @@
     /** Test whether custom actions are attached to the intent. */
     @Test
     @RequiresApi(api = 34)
-    @Config(sdk = 34)
     public void shareWithCustomAction() {
         ShareParams params =
                 new ShareParams.Builder(mWindow, "", JUnitTestGURLs.EXAMPLE_URL.getSpec())
@@ -242,7 +227,6 @@
 
     @Test
     @RequiresApi(api = 34)
-    @Config(sdk = 34)
     public void shareWithoutCustomAction() {
         ShareParams params =
                 new ShareParams.Builder(mWindow, "", "")
@@ -258,7 +242,6 @@
     }
 
     @Test
-    @Config(sdk = 34)
     public void choosePrintAction() throws CanceledException {
         Assume.assumeFalse(
                 "Test ignored in the desktop mode because the Print action is not showed in the"
@@ -354,7 +337,6 @@
     }
 
     @Test
-    @Config(sdk = 34)
     public void shareImageWithCustomActions() {
         Uri testImageUri = Uri.parse("content://test.image.uri");
         ShareParams params =
@@ -380,7 +362,6 @@
     }
 
     @Test
-    @Config(sdk = 34)
     public void shareImageLinkThenCopyImageAndLink() throws CanceledException {
         Uri testImageUri = Uri.parse("content://test.image.uri");
         ShareParams params =
@@ -535,7 +516,6 @@
     }
 
     @Test
-    @Config(sdk = 34)
     public void shareLinkToHighlightText() throws CanceledException {
         ShareParams params =
                 new ShareParams.Builder(mWindow, "", JUnitTestGURLs.EXAMPLE_URL.getSpec())
@@ -586,7 +566,6 @@
 
     @Test
     @RequiresApi(34)
-    @Config(sdk = 34)
     public void shareLinkToHighlightTextFailed() {
         LinkToTextCoordinator.setForceSelectorForTesting("");
 
@@ -625,7 +604,6 @@
     }
 
     @Test
-    @Config(sdk = 34)
     public void shareQrCodeForImage() throws CanceledException {
         QrCodeDialog.setInstanceForTesting(Mockito.mock(QrCodeDialog.class));
         Uri testImageUri = Uri.parse("content://test.image.uri");
@@ -659,7 +637,6 @@
     }
 
     @Test
-    @Config(sdk = 34)
     public void webShareImageLink() throws CanceledException {
         Uri testImageUri = Uri.parse("content://test.image.uri/image.png");
         ShareParams params =
@@ -695,7 +672,6 @@
     }
 
     @Test
-    @Config(sdk = 34)
     public void webShareImageOnly() {
         Uri testImageUri = Uri.parse("content://test.image.uri");
         ShareParams params =
@@ -720,7 +696,6 @@
     }
 
     @Test
-    @Config(sdk = 34)
     public void chooseLongScreenShot() throws CanceledException {
         LongScreenshotsCoordinator mockCoordinator = Mockito.mock(LongScreenshotsCoordinator.class);
         LongScreenshotsCoordinator.setInstanceForTesting(mockCoordinator);
@@ -758,7 +733,6 @@
     }
 
     @Test
-    @Config(sdk = 34)
     public void shareScreenshot() {
         Uri testImageUri = Uri.parse("content://test.screenshot.uri");
         // Build the same params and share extras as sharing a long screenshot
diff --git a/chrome/browser/sync/test/integration/web_apps/two_client_web_apps_integration_test_mac_win_linux.cc b/chrome/browser/sync/test/integration/web_apps/two_client_web_apps_integration_test_mac_win_linux.cc
index 02a36d5..893e609c 100644
--- a/chrome/browser/sync/test/integration/web_apps/two_client_web_apps_integration_test_mac_win_linux.cc
+++ b/chrome/browser/sync/test/integration/web_apps/two_client_web_apps_integration_test_mac_win_linux.cc
@@ -1497,5 +1497,829 @@
   helper_.CheckAppInListTabbed(Site::kStandaloneMigratedSuggested);
 }
 
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_P(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_SwitchProfileClientsClient2_InstallLocallyStandalone_LaunchFromChromeAppsStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseAcceptUpdate_SwitchProfileClientsClient1) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.SwitchProfileClients(ProfileClient::kClient2);
+  helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone);
+  helper_.InstallLocally(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckWindowCreated();
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.SwitchProfileClients(ProfileClient::kClient1);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
 }  // namespace
 }  // namespace web_app::integration_tests
diff --git a/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/TabContentManager.java b/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/TabContentManager.java
index 0816998..0918aff 100644
--- a/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/TabContentManager.java
+++ b/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/TabContentManager.java
@@ -584,13 +584,15 @@
         assert mNativeTabContentManager != 0;
         assert mSnapshotsEnabled;
 
-        if (tab.isHidden()) {
-            Callback.runNullSafe(callback, null);
-            return;
-        }
-
         long startTime = SystemClock.elapsedRealtime();
         if (tab.getNativePage() != null || isNativeViewShowing(tab)) {
+            // Native pages will have their views removed from the view hierarchy when hidden so
+            // capture will not work.
+            if (tab.isHidden()) {
+                Callback.runNullSafe(callback, null);
+                return;
+            }
+
             // If we use readbackNativeBitmap() with a downsampled scale and not saving it through
             // TabContentManagerJni.get().cacheTabWithBitmap(), the logic
             // of InvalidationAwareThumbnailProvider might prevent captureThumbnail() from getting
diff --git a/chrome/browser/task_manager/sampling/task_group_unittest.cc b/chrome/browser/task_manager/sampling/task_group_unittest.cc
index 2d567572..d47376e 100644
--- a/chrome/browser/task_manager/sampling/task_group_unittest.cc
+++ b/chrome/browser/task_manager/sampling/task_group_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/task/sequenced_task_runner.h"
 #include "base/test/gtest_util.h"
 #include "chrome/browser/task_manager/sampling/shared_sampler.h"
+#include "chrome/test/base/chrome_test_utils.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/browser_task_environment.h"
@@ -52,7 +53,9 @@
 
 }  // namespace
 
-class TaskGroupTest : public testing::Test {
+class TaskGroupTest
+    : public chrome_test_utils::TestingBrowserProcessDeathTestMixin,
+      public testing::Test {
  public:
   TaskGroupTest()
       : io_task_runner_(content::GetIOThreadTaskRunner({})),
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index d1d1789..1664c9a9 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -322,6 +322,7 @@
     "//chrome/browser/picture_in_picture",
     "//chrome/browser/picture_in_picture:impl",
     "//chrome/browser/plus_addresses",
+    "//chrome/browser/predictors",
     "//chrome/browser/prefs",
     "//chrome/browser/prefs:impl",
     "//chrome/browser/preloading",
@@ -1428,6 +1429,7 @@
       "//chrome/browser:shell_integration",
       "//chrome/browser/actor/ui",
       "//chrome/browser/actor/ui:actor_overlay",
+      "//chrome/browser/actor/ui:actor_overlay_web_view",
       "//chrome/browser/app_mode",
       "//chrome/browser/apps/app_service",
       "//chrome/browser/apps/app_service/app_icon",
@@ -5476,6 +5478,7 @@
         "//chrome/browser/glic/browser_ui:glow_controller",
         "//chrome/browser/glic/browser_ui:glow_controller_impl",
         "//chrome/browser/glic/browser_ui:glow_impl",
+        "//chrome/browser/glic/selection",
         "//chrome/browser/ui/views/glic",
         "//chrome/browser/ui/views/tabs/glic",
         "//chrome/browser/ui/views/tabs/glic:impl",
diff --git a/chrome/browser/ui/android/extensions/windowing/internal/java/src/org/chromium/chrome/browser/ui/extensions/windowing/ExtensionWindowControllerBridgeIntegrationTest.java b/chrome/browser/ui/android/extensions/windowing/internal/java/src/org/chromium/chrome/browser/ui/extensions/windowing/ExtensionWindowControllerBridgeIntegrationTest.java
index 378b8b6..d091f00 100644
--- a/chrome/browser/ui/android/extensions/windowing/internal/java/src/org/chromium/chrome/browser/ui/extensions/windowing/ExtensionWindowControllerBridgeIntegrationTest.java
+++ b/chrome/browser/ui/android/extensions/windowing/internal/java/src/org/chromium/chrome/browser/ui/extensions/windowing/ExtensionWindowControllerBridgeIntegrationTest.java
@@ -22,6 +22,7 @@
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.CriteriaHelper;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Features;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.Restriction;
@@ -102,6 +103,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "crbug.com/486858979: Temporarily disabled to avoid crashes.")
     public void startWebappActivity_addsExtensionWindowControllerBridgeToChromeAndroidTask() {
         // Act.
         mWebappActivityTestRule.startWebappActivity();
@@ -116,6 +118,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "crbug.com/486858979: Temporarily disabled to avoid crashes.")
     public void startTwa_addsExtensionWindowControllerBridgeToChromeAndroidTask() throws Exception {
         // Act.
         CustomTabActivityTypeTestUtils.launchActivity(
@@ -243,6 +246,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "crbug.com/486858979: Temporarily disabled to avoid crashes.")
     public void startWebappActivity_notifyExtensionInternalsOfWindowCreation() {
         // Arrange:
         // (1) Launch ChromeTabbedActivity. We need this to initialize native
@@ -276,6 +280,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "crbug.com/486858979: Temporarily disabled to avoid crashes.")
     public void startTwa_notifyExtensionInternalsOfWindowCreation() throws Exception {
         // Arrange:
         // (1) Launch ChromeTabbedActivity. We need this to initialize native
@@ -433,6 +438,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "crbug.com/486858979: Temporarily disabled to avoid crashes.")
     public void destroyWebappActivity_destroysExtensionWindowControllerBridge() {
         // Arrange.
         mWebappActivityTestRule.startWebappActivity();
@@ -452,6 +458,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "crbug.com/486858979: Temporarily disabled to avoid crashes.")
     public void destroyTwa_destroysExtensionWindowControllerBridge() throws Exception {
         // Arrange.
         CustomTabActivityTypeTestUtils.launchActivity(
@@ -532,6 +539,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "crbug.com/486858979: Temporarily disabled to avoid crashes.")
     public void destroyWebActivity_notifyExtensionInternalsOfWindowDestruction() {
         // Arrange:
         // (1) Start WebappActivity.
@@ -562,6 +570,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "crbug.com/486858979: Temporarily disabled to avoid crashes.")
     public void destroyTwa_notifyExtensionInternalsOfWindowDestruction() throws Exception {
         // Arrange:
         // (1) Start TWA.
diff --git a/chrome/browser/ui/android/logo/BUILD.gn b/chrome/browser/ui/android/logo/BUILD.gn
index 2e5f7310..1618e2ae 100644
--- a/chrome/browser/ui/android/logo/BUILD.gn
+++ b/chrome/browser/ui/android/logo/BUILD.gn
@@ -8,6 +8,7 @@
 android_library("java") {
   srcjar_deps = [ ":jni_headers" ]
   sources = [
+    "java/src/org/chromium/chrome/browser/logo/DoodleCache.java",
     "java/src/org/chromium/chrome/browser/logo/LogoBridge.java",
     "java/src/org/chromium/chrome/browser/logo/LogoCoordinator.java",
     "java/src/org/chromium/chrome/browser/logo/LogoMediator.java",
@@ -73,6 +74,7 @@
 robolectric_library("junit") {
   resources_package = "org.chromium.chrome.browser.logo"
   sources = [
+    "java/src/org/chromium/chrome/browser/logo/DoodleCacheUnitTest.java",
     "java/src/org/chromium/chrome/browser/logo/LogoCoordinatorUnitTest.java",
     "java/src/org/chromium/chrome/browser/logo/LogoMediatorUnitTest.java",
     "java/src/org/chromium/chrome/browser/logo/LogoUtilsUnitTest.java",
@@ -85,6 +87,7 @@
     ":java_resources",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//base:base_java_test_support_uncommon",
     "//base:base_junit_test_support",
     "//chrome/android:chrome_java",
     "//chrome/browser/flags:java",
diff --git a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/DoodleCache.java b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/DoodleCache.java
new file mode 100644
index 0000000..1337868
--- /dev/null
+++ b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/DoodleCache.java
@@ -0,0 +1,78 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.logo;
+
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.base.ResettersForTesting;
+import org.chromium.base.TimeUtils;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
+import org.chromium.chrome.browser.logo.LogoBridge.Logo;
+
+/**
+ * Caches the search provider doodle to avoid unnecessary network requests and animations. Singleton
+ * class to maintain state across different NTP instances.
+ */
+@NullMarked
+public class DoodleCache {
+    private static @Nullable DoodleCache sInstanceForTesting;
+
+    private @Nullable Logo mCachedDoodle;
+    private long mCachedDoodleTimeMillis;
+    private @Nullable String mCachedDoodleKeyword;
+    // 12 hours cache validity.
+    private static final long CACHE_TTL_MS = 60 * 60 * 1000;
+
+    /** Static class that implements the initialization-on-demand holder idiom. */
+    private static class LazyHolder {
+        static final DoodleCache sInstance = new DoodleCache();
+    }
+
+    /** Returns the singleton instance of DoodleCache. */
+    public static DoodleCache getInstance() {
+        if (sInstanceForTesting != null) {
+            return sInstanceForTesting;
+        }
+        return LazyHolder.sInstance;
+    }
+
+    /** Sets a DoodleCache instance for testing. */
+    public static void setInstanceForTesting(DoodleCache instance) {
+        sInstanceForTesting = instance;
+        ResettersForTesting.register(() -> sInstanceForTesting = null);
+    }
+
+    @VisibleForTesting
+    DoodleCache() {}
+
+    /**
+     * Returns the cached doodle if it is valid and matches the given keyword.
+     *
+     * @param searchEngineKeyword The keyword of the current search engine.
+     * @return The cached Logo, or null if invalid/expired.
+     */
+    public @Nullable Logo getCachedDoodle(@Nullable String searchEngineKeyword) {
+        if (mCachedDoodle != null
+                && searchEngineKeyword != null
+                && searchEngineKeyword.equals(mCachedDoodleKeyword)
+                && (TimeUtils.currentTimeMillis() - mCachedDoodleTimeMillis) < CACHE_TTL_MS) {
+            return mCachedDoodle;
+        }
+        return null;
+    }
+
+    /**
+     * Updates the cached doodle.
+     *
+     * @param doodle The new doodle to cache.
+     * @param searchEngineKeyword The keyword of the search engine associated with the doodle.
+     */
+    public void updateCachedDoodle(Logo doodle, @Nullable String searchEngineKeyword) {
+        mCachedDoodle = doodle;
+        mCachedDoodleTimeMillis = TimeUtils.currentTimeMillis();
+        mCachedDoodleKeyword = searchEngineKeyword;
+    }
+}
diff --git a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/DoodleCacheUnitTest.java b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/DoodleCacheUnitTest.java
new file mode 100644
index 0000000..f3fc3e5
--- /dev/null
+++ b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/DoodleCacheUnitTest.java
@@ -0,0 +1,99 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.logo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import android.graphics.Bitmap;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.FakeTimeTestRule;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.logo.LogoBridge.Logo;
+
+/** Unit tests for the {@link DoodleCache}. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class DoodleCacheUnitTest {
+    @Rule public FakeTimeTestRule mFakeTimeTestRule = new FakeTimeTestRule();
+
+    private DoodleCache mDoodleCache;
+    private Logo mLogo;
+
+    @Before
+    public void setUp() {
+        mDoodleCache = new DoodleCache();
+        DoodleCache.setInstanceForTesting(mDoodleCache);
+        Bitmap bitmap = Bitmap.createBitmap(/* width= */ 1, /* height= */ 1, Bitmap.Config.ALPHA_8);
+        mLogo =
+                new Logo(
+                        bitmap,
+                        /* onClickUrl= */ null,
+                        /* altText= */ null,
+                        /* animatedLogoUrl= */ null);
+    }
+
+    @After
+    public void tearDown() {
+        DoodleCache.setInstanceForTesting(null);
+    }
+
+    @Test
+    public void testCacheAndRetrieve() {
+        String keyword = "keyword";
+        mDoodleCache.updateCachedDoodle(mLogo, keyword);
+        assertEquals(mLogo, mDoodleCache.getCachedDoodle(keyword));
+    }
+
+    @Test
+    public void testCacheMissKeywordMismatch() {
+        String keyword = "keyword";
+        mDoodleCache.updateCachedDoodle(mLogo, keyword);
+        assertNull(mDoodleCache.getCachedDoodle("other"));
+    }
+
+    @Test
+    public void testCacheMissNullKeyword() {
+        String keyword = "keyword";
+        mDoodleCache.updateCachedDoodle(mLogo, keyword);
+        assertNull(mDoodleCache.getCachedDoodle(/* searchEngineKeyword= */ null));
+    }
+
+    @Test
+    public void testCacheExpiration() {
+        String keyword = "keyword";
+        mDoodleCache.updateCachedDoodle(mLogo, keyword);
+
+        // Advance time by 12 hours + 1 ms.
+        mFakeTimeTestRule.advanceMillis(12 * 60 * 60 * 1000 + 1);
+
+        assertNull(mDoodleCache.getCachedDoodle(keyword));
+    }
+
+    @Test
+    public void testUpdateReplacesCache() {
+        String keyword = "keyword";
+        mDoodleCache.updateCachedDoodle(mLogo, keyword);
+
+        Bitmap bitmap2 =
+                Bitmap.createBitmap(/* width= */ 1, /* height= */ 1, Bitmap.Config.ARGB_8888);
+        Logo logo2 =
+                new Logo(
+                        bitmap2,
+                        /* onClickUrl= */ null,
+                        /* altText= */ null,
+                        /* animatedLogoUrl= */ null);
+
+        mDoodleCache.updateCachedDoodle(logo2, keyword);
+        assertEquals(logo2, mDoodleCache.getCachedDoodle(keyword));
+    }
+}
diff --git a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediator.java b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediator.java
index 575339c..83135b3 100644
--- a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediator.java
+++ b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediator.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.logo;
 
+import static org.chromium.build.NullUtil.assumeNonNull;
 import static org.chromium.chrome.browser.ntp_customization.NtpCustomizationUtils.doesDefaultSearchEngineHaveLogo;
 
 import android.graphics.ImageDecoder;
@@ -35,6 +36,7 @@
 import org.chromium.components.image_fetcher.ImageFetcherConfig;
 import org.chromium.components.image_fetcher.ImageFetcherFactory;
 import org.chromium.components.search_engines.TemplateUrl;
+import org.chromium.components.search_engines.TemplateUrlService;
 import org.chromium.components.search_engines.TemplateUrlService.TemplateUrlServiceObserver;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.base.PageTransition;
@@ -140,6 +142,13 @@
         }
 
         mProfile = profile;
+
+        TemplateUrlService templateUrlService = TemplateUrlServiceFactory.getForProfile(mProfile);
+        TemplateUrl templateUrl = templateUrlService.getDefaultSearchEngineTemplateUrl();
+        if (templateUrl != null) {
+            mSearchEngineKeyword = templateUrl.getKeyword();
+        }
+
         updateVisibility();
 
         if (mShouldShowLogo) {
@@ -147,7 +156,7 @@
             if (mIsLoadPending) loadSearchProviderLogo(/* animationEnabled= */ false);
         }
 
-        TemplateUrlServiceFactory.getForProfile(mProfile).addObserver(this);
+        templateUrlService.addObserver(this);
     }
 
     /** Update the logo based on default search engine changes. */
@@ -239,8 +248,25 @@
         // record, don't bother loading the logo image.
         if (mHasLogoLoadedForCurrentSearchEngine || mProfile == null || !mShouldShowLogo) return;
 
+        @Nullable Logo cachedDoodle =
+                DoodleCache.getInstance().getCachedDoodle(mSearchEngineKeyword);
+        boolean isCacheHit = cachedDoodle != null;
+
         mHasLogoLoadedForCurrentSearchEngine = true;
-        mLogoModel.set(LogoProperties.ANIMATION_ENABLED, animationEnabled);
+        // Disable animation if it's a cache hit.
+        mLogoModel.set(LogoProperties.ANIMATION_ENABLED, animationEnabled && !isCacheHit);
+
+        if (isCacheHit) {
+            updateModelWithLogo(cachedDoodle);
+            RecordHistogram.recordEnumeratedHistogram(
+                    LOGO_SHOWN_FROM_CACHE_UMA_NAME,
+                    assumeNonNull(cachedDoodle).animatedLogoUrl == null
+                            ? LogoShownId.STATIC_LOGO_SHOWN
+                            : LogoShownId.CTA_IMAGE_SHOWN,
+                    LogoShownId.LOGO_SHOWN_COUNT);
+            return;
+        }
+
         showSearchProviderInitialView();
 
         if (mLogoBridge == null) {
@@ -270,14 +296,22 @@
                                     LogoProperties.DEFAULT_GOOGLE_LOGO_DRAWABLE,
                                     getDefaultGoogleLogoDrawable());
                         }
-                        mLogoModel.set(
-                                LogoProperties.LOGO_CLICK_HANDLER,
-                                LogoMediator.this::onLogoClicked);
-                        mLogoModel.set(LogoProperties.LOGO, logo);
+                        updateModelWithLogo(logo);
+                        DoodleCache.getInstance().updateCachedDoodle(logo, mSearchEngineKeyword);
                     }
                 });
     }
 
+    /**
+     * Updates the model with the provided logo and sets the click handler.
+     *
+     * @param logo The logo to set in the model.
+     */
+    private void updateModelWithLogo(@Nullable Logo logo) {
+        mLogoModel.set(LogoProperties.LOGO_CLICK_HANDLER, LogoMediator.this::onLogoClicked);
+        mLogoModel.set(LogoProperties.LOGO, logo);
+    }
+
     private void showSearchProviderInitialView() {
         mLogoModel.set(LogoProperties.DEFAULT_GOOGLE_LOGO_DRAWABLE, getDefaultGoogleLogoDrawable());
 
diff --git a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediatorUnitTest.java b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediatorUnitTest.java
index 0257f84..8867bde 100644
--- a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediatorUnitTest.java
+++ b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediatorUnitTest.java
@@ -20,6 +20,7 @@
 
 import androidx.test.core.app.ApplicationProvider;
 
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
@@ -66,10 +67,14 @@
 
     @Mock Callback<Logo> mOnLogoAvailableCallback;
 
+    @Mock DoodleCache mDoodleCache;
+
     @Captor
     private ArgumentCaptor<TemplateUrlService.TemplateUrlServiceObserver>
             mTemplateUrlServiceObserverArgumentCaptor;
 
+    @Captor private ArgumentCaptor<LogoBridge.LogoObserver> mLogoObserverArgumentCaptor;
+
     private Context mContext;
     private PropertyModel mLogoModel;
 
@@ -83,6 +88,7 @@
         when(mTemplateUrlService.getDefaultSearchEngineTemplateUrl()).thenReturn(mTemplateUrl);
         when(mTemplateUrl.getKeyword()).thenReturn(null);
 
+        DoodleCache.setInstanceForTesting(mDoodleCache);
         LogoBridgeJni.setInstanceForTesting(mLogoBridgeJniMock);
 
         ThreadUtils.runOnUiThreadBlocking(
@@ -91,6 +97,11 @@
         mLogoModel = new PropertyModel(LogoProperties.ALL_KEYS);
     }
 
+    @After
+    public void tearDown() {
+        DoodleCache.setInstanceForTesting(null);
+    }
+
     @Test
     public void testDseChangedAndGoogleIsDseAndDoodleIsSupported() {
         LogoMediator logoMediator = createMediator(mContext.getDrawable(R.drawable.ic_google_logo));
@@ -140,6 +151,37 @@
     }
 
     @Test
+    public void testLoadLogoUpdatesCache() {
+        LogoMediator logoMediator = createMediator();
+        logoMediator.setHasLogoLoadedForCurrentSearchEngineForTesting(false);
+        when(mTemplateUrlService.isDefaultSearchEngineGoogle()).thenReturn(false);
+        Logo logo = mock(Logo.class);
+
+        logoMediator.updateVisibility(/* animationEnabled= */ false);
+
+        verify(mLogoBridge).getCurrentLogo(mLogoObserverArgumentCaptor.capture());
+        mLogoObserverArgumentCaptor.getValue().onLogoAvailable(logo, false);
+
+        verify(mDoodleCache).updateCachedDoodle(logo, null);
+    }
+
+    @Test
+    public void testLoadLogoFromCache() {
+        LogoMediator logoMediator = createMediator();
+        logoMediator.setHasLogoLoadedForCurrentSearchEngineForTesting(false);
+        Logo cachedLogo = mock(Logo.class);
+        when(mDoodleCache.getCachedDoodle(any())).thenReturn(cachedLogo);
+
+        logoMediator.updateVisibility(/* animationEnabled= */ true);
+
+        // Should use cached logo and not call bridge
+        verify(mLogoBridge, never()).getCurrentLogo(any());
+        assertEquals(cachedLogo, mLogoModel.get(LogoProperties.LOGO));
+        // Animation should be disabled when loading from cache
+        Assert.assertFalse(mLogoModel.get(LogoProperties.ANIMATION_ENABLED));
+    }
+
+    @Test
     public void testLoadLogoWhenLogoHasLoaded() {
         LogoMediator logoMediator = createMediator();
         logoMediator.setHasLogoLoadedForCurrentSearchEngineForTesting(true);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/FuseboxSessionState.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/FuseboxSessionState.java
index 48d1774..897e710d 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/FuseboxSessionState.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/FuseboxSessionState.java
@@ -10,13 +10,14 @@
 import org.chromium.base.UserDataHost;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.components.embedder_support.util.UrlUtilities;
 import org.chromium.components.omnibox.AutocompleteInput;
 import org.chromium.components.omnibox.OmniboxFeatures;
 
 /**
  * Fusebox / Omnibox session state object. Captures controllers and state details needed to fulfill
- * or reconstruct the user input.
+ * or reconstruct the user input. This object is associated with a specific {@link Profile}.
  *
  * <p>Unlike the AutocompleteInput - this class is permitted to hold external controllers required
  * to fulfill navigation request.
@@ -29,6 +30,7 @@
      */
     private AutocompleteInput mAutocompleteInput = new AutocompleteInput();
 
+    private @Nullable Profile mProfile;
     private boolean mIsActive;
 
     /**
@@ -36,7 +38,8 @@
      * exists.
      *
      * @param dataProvider The {@link LocationBarDataProvider} to retrieve the current tab from.
-     * @return FuseboxSessionState appropriate for the supplied LocationBarDataProvider.
+     * @return FuseboxSessionState appropriate for the supplied LocationBarDataProvider, or `null`
+     *     if the UserData to host the persisted session state is not available.
      */
     public static @Nullable FuseboxSessionState from(LocationBarDataProvider dataProvider) {
         var userDataHost = dataProvider.getUserDataHost();
@@ -65,6 +68,26 @@
         return state;
     }
 
+    /** Constructs a new, empty FuseboxSessionState. */
+    private FuseboxSessionState() {}
+
+    /**
+     * Constructs a new FuseboxSessionState with a provided AutocompleteInput.
+     *
+     * @param input The initial AutocompleteInput for this session.
+     */
+    @VisibleForTesting
+    public FuseboxSessionState(AutocompleteInput input) {
+        mAutocompleteInput = input;
+    }
+
+    /**
+     * @return The current {@link Profile} for this session.
+     */
+    public @Nullable Profile getProfile() {
+        return mProfile;
+    }
+
     /**
      * Marks the session as active or inactive. When session is marked as inactive, the autocomplete
      * input is reset.
@@ -72,8 +95,7 @@
      * @param isActive Whether the session should be active.
      */
     public void setSessionActive(boolean isActive) {
-        if (isActive == mIsActive) return;
-
+        if (mIsActive == isActive) return;
         mIsActive = isActive;
         if (isActive) {
             mAutocompleteInput.setUrlFocusTime(System.currentTimeMillis());
@@ -87,10 +109,21 @@
             }
         } else {
             mAutocompleteInput.reset();
+            setProfile(null);
         }
     }
 
     /**
+     * Apply or reset profile to be used with the current Fusebox session.
+     *
+     * @param profile The profile the session is activated for; must be supplied to activate the
+     *     session.
+     */
+    public void setProfile(@Nullable Profile profile) {
+        mProfile = profile;
+    }
+
+    /**
      * @return Whether the Fusebox session is active.
      */
     public boolean isSessionActive() {
@@ -108,17 +141,4 @@
     public AutocompleteInput getAutocompleteInput() {
         return mAutocompleteInput;
     }
-
-    /**
-     * Constructs a new FuseboxSessionState with a provided AutocompleteInput.
-     *
-     * @param input The initial AutocompleteInput for this session.
-     */
-    @VisibleForTesting
-    public FuseboxSessionState(AutocompleteInput input) {
-        mAutocompleteInput = input;
-    }
-
-    /** Constructs a new, empty FuseboxSessionState. */
-    FuseboxSessionState() {}
 }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index 713d708..f0dcf7d 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -46,7 +46,7 @@
     protected ImageButton mZoomButton;
     protected ImageButton mInstallButton;
     protected ImageButton mComposeplateButton;
-    private final @Nullable View mNavigateButton;
+    protected final @Nullable View mNavigateButton;
     protected UrlBar mUrlBar;
 
     protected UrlBarCoordinator mUrlCoordinator;
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
index 3f6f8ca5..befd2cf 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
@@ -1045,19 +1045,17 @@
      *
      * @param activateNewSession Whether to begin a new input session if one is not already active.
      *     Active input sessions show Autocomplete and focused Omnibox.
-     * @return true if new input session has been activated.
      */
     @EnsuresNonNullIf("mCurrentInput")
     @VisibleForTesting
-    boolean beginOrResumeInput(boolean activateNewSession) {
-        if (mAutocompleteCoordinator == null) return false;
+    void beginOrResumeInput(boolean activateNewSession) {
         // Do not instantiate a new ephemeral session unless we're activating it as well.
         var session = FuseboxSessionState.from(mLocationBarDataProvider);
 
         // Target session must be either active, or activated.
         if (session == null || !(session.isSessionActive() || activateNewSession)) {
             endInputInternal();
-            return false;
+            return;
         }
 
         // If we're switching tab (active -> active), just reanchor observer.
@@ -1073,30 +1071,23 @@
         mUrlCoordinator.setUrlBarData(
                 data, UrlBar.ScrollType.NO_SCROLL, mCurrentInput.getSelection());
 
-        // In the event input session was activated before native initialization we cannot
-        // correctly determine the page classification, rendering the AutocompleteInput
-        // instance not sufficiently valid to facilitate Autocomplete.
-        if (mNativeInitialized) {
-            mAutocompleteCoordinator.beginInput(session);
-            mFuseboxCoordinator.beginInput(session);
-        } else {
-            mDeferredNativeRunnables.add(
-                    () -> {
-                        // mCurrentInput's timeline is fully contained within the mUrlHasFocus'
-                        // timeline. The check below confirms the mUrlHasFocus and ensures
-                        // mCurrentInput is not null.
-                        if (mCurrentInput == null) return;
-                        mCurrentInput.setPageClassification(
-                                mLocationBarDataProvider.getPageClassification(
-                                        /* prefetch= */ false));
-                        if (mAutocompleteCoordinator != null) {
-                            mAutocompleteCoordinator.beginInput(session);
-                            mFuseboxCoordinator.beginInput(session);
-                        }
-                    });
+        // URL bar is now focused with the user text. This may be still a bit early for the
+        // Autocomplete and Compose to kick in.
+        beginOrResumeInputWithNative();
+    }
+
+    private void beginOrResumeInputWithNative() {
+        if (!mNativeInitialized) {
+            mDeferredNativeRunnables.add(this::beginOrResumeInputWithNative);
+            return;
         }
 
-        return true;
+        if (mAutocompleteCoordinator == null) return;
+        var session = FuseboxSessionState.from(mLocationBarDataProvider);
+        if (session == null || !session.isSessionActive()) return;
+        session.setProfile(mProfileSupplier.get());
+        mAutocompleteCoordinator.beginInput(session);
+        mFuseboxCoordinator.beginInput(session);
     }
 
     /** Ends the current Omnibox input session. */
@@ -2014,11 +2005,6 @@
      */
     @Override
     public void beginInput(AutocompleteInput input) {
-        boolean isSearchQuery = input.getFocusReason() == OmniboxFocusReason.SEARCH_QUERY;
-        if (isSearchQuery && !mNativeInitialized) {
-            mDeferredNativeRunnables.add(() -> beginInput(input));
-            return;
-        }
         input.setPageClassification(mLocationBarDataProvider.getPageClassification(false));
         input.setPageUrl(mLocationBarDataProvider.getCurrentGurl());
         input.setPageTitle(mLocationBarDataProvider.getTitle());
@@ -2044,10 +2030,6 @@
 
         // Wait for the Url focus change before refreshing autocomplete.
         beginOrResumeInput(/* activateNewSession= */ true);
-
-        if (isSearchQuery) {
-            mUrlCoordinator.setKeyboardVisibility(true, false);
-        }
     }
 
     /**
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java
index 9ba8e83d..8da17a70 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java
@@ -453,7 +453,7 @@
         verify(mUrlCoordinator)
                 .setAutocompleteText("text", "textWithAutocomplete", "additionalText", null);
 
-        var state = FuseboxSessionState.from(mLocationBarDataProvider);
+        var state = getSession();
         state.getAutocompleteInput().setRequestType(AutocompleteRequestType.AI_MODE);
         mMediator.onSuggestionsChanged(defaultMatch, true);
         verify(mStatusCoordinator, times(2)).onDefaultMatchClassified(true);
@@ -1565,7 +1565,7 @@
         doReturn("text").when(mUrlCoordinator).getTextWithAutocomplete();
         mMediator.onUrlFocusChange(true);
 
-        var state = FuseboxSessionState.from(mLocationBarDataProvider);
+        var state = getSession();
         state.getAutocompleteInput().setRequestType(AutocompleteRequestType.SEARCH);
         assertTrue(mNavigateButtonIsVisible);
 
@@ -1715,7 +1715,7 @@
 
         // Prepare a state to be restored for mTab.
         String newText = "new text";
-        var newState = FuseboxSessionState.from(mLocationBarDataProvider);
+        var newState = getSession();
         newState.getAutocompleteInput().setUserText(newText);
         newState.setSessionActive(true);
 
@@ -1729,7 +1729,7 @@
         mTabletMediator.onUrlFocusChange(true);
         String previousText = "previous text";
         // Note: input state is tracked by autocomplete.
-        var previousState = FuseboxSessionState.from(mLocationBarDataProvider);
+        var previousState = getSession();
         previousState.getAutocompleteInput().setUserText(previousText);
 
         // Emulate a tab switch from previousTab to mTab.
@@ -1766,7 +1766,7 @@
         String newText = "new text";
         final int newSelectionStart = 2;
         final int newSelectionEnd = 6;
-        var newState = FuseboxSessionState.from(mLocationBarDataProvider);
+        var newState = getSession();
         newState.getAutocompleteInput().setUserText(newText);
         newState.getAutocompleteInput().setSelection(newSelectionStart, newSelectionEnd);
         newState.setSessionActive(true);
@@ -1784,7 +1784,7 @@
         final int previousSelectionEnd = 5;
 
         // Note: input state is tracked by autocomplete.
-        var previousState = FuseboxSessionState.from(mLocationBarDataProvider);
+        var previousState = getSession();
         previousState.getAutocompleteInput().setUserText(previousText);
         doReturn(previousSelectionStart).when(mUrlCoordinator).getSelectionStart();
         doReturn(previousSelectionEnd).when(mUrlCoordinator).getSelectionEnd();
@@ -2144,4 +2144,8 @@
         verify(mLocationBarEmbedder, never()).onWidthConsumerVisibilityChanged();
         Mockito.clearInvocations(mLocationBarTablet, mLocationBarEmbedder);
     }
+
+    private FuseboxSessionState getSession() {
+        return FuseboxSessionState.from(mLocationBarDataProvider);
+    }
 }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
index 33a196a..7454e51 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
@@ -12,6 +12,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.GradientDrawable;
 import android.graphics.drawable.LayerDrawable;
+import android.os.Handler;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.MotionEvent;
@@ -47,6 +48,7 @@
     private View[] mTargets;
     private final Rect mCachedTargetBounds = new Rect();
     private final GlifStrokeDrawable mGlifBorderDrawable;
+    private final Handler mHandler;
 
     // Variables needed for animating the location bar and toolbar buttons hiding/showing.
     private final int mToolbarButtonsWidth;
@@ -65,6 +67,7 @@
     private WindowAndroid mWindowAndroid;
     private @FuseboxState int mFuseboxState;
     private boolean mHasSuggestions;
+    private int mScreenWidthDp;
 
     /** Constructor used to inflate from XML. */
     public LocationBarTablet(Context context, AttributeSet attrs) {
@@ -85,6 +88,7 @@
                                         R.drawable
                                                 .modern_toolbar_tablet_text_box_background_focused_popup));
         mGlifBorderDrawable = new GlifStrokeDrawable(context);
+        mHandler = new Handler();
     }
 
     @Override
@@ -119,6 +123,7 @@
         setOnLongClickListener(this);
 
         mTargets = new View[] {mUrlBar, mDeleteButton};
+        mScreenWidthDp = getResources().getConfiguration().screenWidthDp;
     }
 
     @SuppressLint("ClickableViewAccessibility")
@@ -176,6 +181,17 @@
         if (mAnimatingWidthChange) {
             setWidthChangeAnimationFraction(mWidthChangeFraction);
         }
+
+        int screenWidthDp = getResources().getConfiguration().screenWidthDp;
+        boolean widthChangedSinceLastLayout = screenWidthDp != mScreenWidthDp;
+        if (widthChangedSinceLastLayout) {
+            // Our fusebox-specific margins become wrong when the window width changes, since they
+            // depend on the window width. When we detect that the window width changes, recalculate
+            // margins for the current state + new width using a post(), whose delay allows the full
+            // layout pass to finish.
+            mScreenWidthDp = screenWidthDp;
+            mHandler.post(() -> onFuseboxStateChanged(mFuseboxState));
+        }
     }
 
     /** Returns amount by which to adjust to move value inside the given range. */
@@ -470,7 +486,8 @@
         ViewUtils.getRelativeLayoutPosition(getRootView(), this, mPositionArray);
         int currentLeft = mPositionArray[0];
         // Our view is relatively centered already; make it exactly centered when expanded.
-        boolean isViewApproximatelyCentered = windowWidthPx - 2 * currentLeft <= minTabletWidthPx;
+        boolean isViewApproximatelyCentered =
+                windowWidthPx - 2 * currentLeft <= minTabletWidthPx || isPhoneWidthScreen;
         if (isViewApproximatelyCentered) {
             int targetLeft = (windowWidthPx - targetWidthPx) / 2;
             int targetRight = targetLeft + targetWidthPx;
@@ -479,8 +496,8 @@
             int shiftLeft = targetLeft - currentLeft;
             int shiftRight = targetRight - currentRight;
 
-            layoutParams.leftMargin = shiftLeft;
-            layoutParams.rightMargin = -shiftRight;
+            layoutParams.leftMargin += shiftLeft;
+            layoutParams.rightMargin -= shiftRight;
         } else {
             // Our view is relatively off-center. Leave it that way, expanding symmetrically from
             // our current position.
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarTabletUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarTabletUnitTest.java
index e7c56b55..3708c96 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarTabletUnitTest.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarTabletUnitTest.java
@@ -26,7 +26,9 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowLooper;
 import org.robolectric.shadows.ShadowToast;
 
 import org.chromium.base.MathUtils;
@@ -245,6 +247,43 @@
         assertEquals(-translationY, micButton.getTranslationY(), MathUtils.EPSILON);
     }
 
+    @Test
+    @EnableFeatures(OmniboxFeatureList.OMNIBOX_MULTIMODAL_INPUT)
+    @Config(qualifiers = "w800dp-mdpi")
+    public void testWindowWidthChangedMarginCalcs() {
+        int prefocusWidth = 400;
+        mLocationBarTablet.measure(
+                MeasureSpec.makeMeasureSpec(prefocusWidth, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY));
+        mLocationBarTablet.onFuseboxStateChanged(FuseboxState.EXPANDED);
+        int minWidthPx =
+                mLocationBarTablet
+                        .getResources()
+                        .getDimensionPixelSize(R.dimen.fusebox_min_tablet_width);
+        LinearLayout.LayoutParams layoutParams =
+                (LinearLayout.LayoutParams) mLocationBarTablet.getLayoutParams();
+        int expectedMargin = -((minWidthPx - prefocusWidth) / 2);
+        assertEquals(expectedMargin, layoutParams.leftMargin);
+        assertEquals(expectedMargin, layoutParams.rightMargin);
+
+        RuntimeEnvironment.setQualifiers("w599dp-mdpi");
+        mLocationBarTablet.measure(
+                MeasureSpec.makeMeasureSpec(prefocusWidth, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY));
+        mLocationBarTablet.layout(
+                0,
+                0,
+                mLocationBarTablet.getMeasuredWidth(),
+                mLocationBarTablet.getMeasuredHeight());
+        ShadowLooper.idleMainLooper();
+        layoutParams = (LinearLayout.LayoutParams) mLocationBarTablet.getLayoutParams();
+        assertEquals(expectedMargin, layoutParams.leftMargin);
+        assertEquals(
+                expectedMargin - (599 * DIP_SCALE - mLocationBarTablet.getMeasuredWidth()),
+                layoutParams.rightMargin,
+                MathUtils.EPSILON);
+    }
+
     private void longClickAndVerifyToast(int viewId, int stringId) {
         mLocationBarTablet.onLongClick(mLocationBarTablet.findViewById(viewId));
         assertTrue(
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediator.java
index bdda517..d0e5af3 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediator.java
@@ -47,6 +47,7 @@
 import org.chromium.chrome.browser.ui.theme.BrandedColorScheme;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.components.browser_ui.util.ChromeItemPickerExtras;
+import org.chromium.components.browser_ui.util.ChromeItemPickerUtils;
 import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.components.omnibox.AutocompleteInput;
 import org.chromium.components.omnibox.AutocompleteRequestType;
@@ -182,6 +183,7 @@
     /** Called when the user stops interacting with the Omnibox. */
     /* package */ void endInput() {
         mModelList.clear();
+        mPopup.dismiss();
         setToolbarVisible(false);
         setAutocompleteInput(null);
     }
@@ -435,37 +437,20 @@
     void onTabPickerClicked() {
         mPopup.dismiss();
         FuseboxMetrics.notifyAttachmentButtonUsed(FuseboxAttachmentButtonType.TAB_PICKER);
-        int remainingAttachments = mModelList.getRemainingAttachments();
         if (isMaxAttachmentCountReached(FuseboxAttachmentType.ATTACHMENT_TAB)) return;
 
-        Intent intent;
-        ArrayList<Integer> preselectedTabIds = new ArrayList<>(mModelList.getAttachedTabIds());
-        try {
-            intent =
-                    new Intent(
-                                    mContext,
-                                    Class.forName(
-                                            ChromeItemPickerExtras
-                                                    .CHROME_ITEM_PICKER_ACTIVITY_CLASS))
-                            .putIntegerArrayListExtra(
-                                    ChromeItemPickerExtras.EXTRA_PRESELECTED_TAB_IDS,
-                                    preselectedTabIds);
-            ProfileIntentUtils.addProfileToIntent(mProfile, intent);
+        Intent intent = ChromeItemPickerUtils.createChromeItemPickerIntent(mContext);
+        if (intent == null) return;
+        ProfileIntentUtils.addProfileToIntent(mProfile, intent);
 
-            TabModelSelector tabModelSelector = mTabModelSelectorSupplier.get();
-            boolean isIncognitoBrandedModelSelected = false;
-            if (tabModelSelector != null) {
-                isIncognitoBrandedModelSelected =
-                        tabModelSelector.isIncognitoBrandedModelSelected();
-            }
-            intent.putExtra(
-                    ChromeItemPickerExtras.EXTRA_IS_INCOGNITO_BRANDED,
-                    isIncognitoBrandedModelSelected);
-        } catch (ClassNotFoundException e) {
-            return;
-        }
+        ArrayList<Integer> tabIds = new ArrayList<>(mModelList.getAttachedTabIds());
+        intent.putIntegerArrayListExtra(ChromeItemPickerExtras.EXTRA_PRESELECTED_TAB_IDS, tabIds);
 
-        int maxAllowedTabs = preselectedTabIds.size() + remainingAttachments;
+        TabModelSelector selector = mTabModelSelectorSupplier.get();
+        boolean isIncognito = selector != null && selector.isIncognitoBrandedModelSelected();
+        intent.putExtra(ChromeItemPickerExtras.EXTRA_IS_INCOGNITO_BRANDED, isIncognito);
+
+        int maxAllowedTabs = tabIds.size() + mModelList.getRemainingAttachments();
         intent.putExtra(ChromeItemPickerExtras.EXTRA_ALLOWED_SELECTION_COUNT, maxAllowedTabs);
 
         boolean isSingleContextMode = !OmniboxFeatures.sMultiattachmentFusebox.getValue();
@@ -565,10 +550,11 @@
                         && allowByCapacity;
 
         mModel.set(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_ENABLED, allowNonImage);
-        mModel.set(FuseboxProperties.POPUP_ATTACH_FILE_ENABLED, allowNonImage);
         mModel.set(FuseboxProperties.POPUP_ATTACH_TAB_PICKER_ENABLED, allowNonImage);
+        mModel.set(FuseboxProperties.POPUP_ATTACH_CLIPBOARD_ENABLED, allowByCapacity);
         mModel.set(FuseboxProperties.POPUP_ATTACH_CAMERA_ENABLED, allowByCapacity);
         mModel.set(FuseboxProperties.POPUP_ATTACH_GALLERY_ENABLED, allowByCapacity);
+        mModel.set(FuseboxProperties.POPUP_ATTACH_FILE_ENABLED, allowNonImage);
     }
 
     @VisibleForTesting
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediatorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediatorUnitTest.java
index 317189d..01bbded 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediatorUnitTest.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediatorUnitTest.java
@@ -75,6 +75,7 @@
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.ui.theme.BrandedColorScheme;
 import org.chromium.components.browser_ui.util.ChromeItemPickerExtras;
+import org.chromium.components.browser_ui.util.ChromeItemPickerUtils;
 import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.components.metrics.OmniboxEventProtos.OmniboxEventProto.PageClassification;
 import org.chromium.components.omnibox.AutocompleteInput;
@@ -331,6 +332,15 @@
     }
 
     @Test
+    public void testEndInput_DismissesPopup() {
+        mModel.get(FuseboxProperties.BUTTON_ADD_CLICKED).run();
+        verify(mPopup).show();
+
+        mMediator.endInput();
+        verify(mPopup).dismiss();
+    }
+
+    @Test
     public void popupAddsTabs() {
         assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_VISIBLE));
         doReturn(mTab1).when(mTabModelSelector).getCurrentTab();
@@ -494,17 +504,17 @@
         mModel.get(FuseboxProperties.BUTTON_ADD_CLICKED).run();
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_VISIBLE));
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_ENABLED));
+        assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_TAB_PICKER_ENABLED));
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_FILE_VISIBLE));
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_FILE_ENABLED));
-        assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_TAB_PICKER_ENABLED));
 
         mModel.get(FuseboxProperties.POPUP_TOOL_CREATE_IMAGE_CLICKED).run();
         mModel.get(FuseboxProperties.BUTTON_ADD_CLICKED).run();
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_VISIBLE));
         assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_ENABLED));
+        assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_TAB_PICKER_ENABLED));
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_FILE_VISIBLE));
         assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_FILE_ENABLED));
-        assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_TAB_PICKER_ENABLED));
     }
 
     @Test
@@ -760,8 +770,7 @@
         verify(mWindowAndroid).showCancelableIntent(mIntentCaptor.capture(), any(), any());
         Intent intent = mIntentCaptor.getValue();
         assertEquals(
-                ChromeItemPickerExtras.CHROME_ITEM_PICKER_ACTIVITY_CLASS,
-                intent.getComponent().getClassName());
+                ChromeItemPickerUtils.ACTIVITY_CLASS_NAME, intent.getComponent().getClassName());
         assertNotNull(
                 intent.getIntegerArrayListExtra(ChromeItemPickerExtras.EXTRA_PRESELECTED_TAB_IDS));
         assertEquals(
@@ -937,43 +946,45 @@
     @Test
     public void testUpdatePopupButtonEnabledStates_maxAttachmentsReached() {
         mInput.setRequestType(AutocompleteRequestType.SEARCH);
+        assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_ENABLED));
+        assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_TAB_PICKER_ENABLED));
+        assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_CLIPBOARD_ENABLED));
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_CAMERA_ENABLED));
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_GALLERY_ENABLED));
-        assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_TAB_PICKER_ENABLED));
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_FILE_ENABLED));
-        assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_ENABLED));
 
-        // Add maximum attachments
+        // Add maximum attachments.
         for (int i = 0; i < FuseboxAttachmentModelList.getMaxAttachments(); i++) {
             addAttachment("file" + i, "token" + i, FuseboxAttachmentType.ATTACHMENT_FILE);
         }
         assertEquals(0, mAttachments.getRemainingAttachments());
-
+        assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_ENABLED));
+        assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_TAB_PICKER_ENABLED));
+        assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_CLIPBOARD_ENABLED));
         assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_CAMERA_ENABLED));
         assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_GALLERY_ENABLED));
-        assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_TAB_PICKER_ENABLED));
-        assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_ENABLED));
         assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_FILE_ENABLED));
 
-        // Remove one attachment to free up space
+        // Remove one attachment to free up space.
         mAttachments.remove(mAttachments.get(0), /* isFailure= */ false);
         assertTrue(mAttachments.getRemainingAttachments() > 0);
-
+        assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_ENABLED));
+        assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_TAB_PICKER_ENABLED));
+        assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_CLIPBOARD_ENABLED));
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_CAMERA_ENABLED));
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_GALLERY_ENABLED));
-        assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_TAB_PICKER_ENABLED));
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_FILE_ENABLED));
-        assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_ENABLED));
     }
 
     @Test
     public void testUpdatePopupButtonEnabledStates_modeChanges() {
         mInput.setRequestType(AutocompleteRequestType.IMAGE_GENERATION);
 
+        assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_ENABLED));
+        assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_TAB_PICKER_ENABLED));
+        assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_CLIPBOARD_ENABLED));
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_CAMERA_ENABLED));
         assertTrue(mModel.get(FuseboxProperties.POPUP_ATTACH_GALLERY_ENABLED));
-        assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_TAB_PICKER_ENABLED));
-        assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_CURRENT_TAB_ENABLED));
         assertFalse(mModel.get(FuseboxProperties.POPUP_ATTACH_FILE_ENABLED));
     }
 
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxProperties.java
index 1fe1c5b..9cf3091 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxProperties.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxProperties.java
@@ -65,6 +65,10 @@
     public static final WritableObjectPropertyKey<Runnable> POPUP_ATTACH_CLIPBOARD_CLICKED =
             new WritableObjectPropertyKey<>();
 
+    /** Whether the Clipboard button in the popup is enabled. */
+    public static final WritableBooleanPropertyKey POPUP_ATTACH_CLIPBOARD_ENABLED =
+            new WritableBooleanPropertyKey();
+
     /** Whether the Clipboard button in the popup is visible. */
     public static final WritableBooleanPropertyKey POPUP_ATTACH_CLIPBOARD_VISIBLE =
             new WritableBooleanPropertyKey();
@@ -157,6 +161,7 @@
         POPUP_ATTACH_CAMERA_CLICKED,
         POPUP_ATTACH_CAMERA_ENABLED,
         POPUP_ATTACH_CLIPBOARD_CLICKED,
+        POPUP_ATTACH_CLIPBOARD_ENABLED,
         POPUP_ATTACH_CLIPBOARD_VISIBLE,
         POPUP_ATTACH_CURRENT_TAB_CLICKED,
         POPUP_ATTACH_CURRENT_TAB_ENABLED,
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxViewBinder.java
index dbff1597..ce08373 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxViewBinder.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxViewBinder.java
@@ -96,6 +96,9 @@
         } else if (propertyKey == FuseboxProperties.POPUP_ATTACH_CLIPBOARD_CLICKED) {
             view.popup.mClipboardButton.setOnClickListener(
                     v -> model.get(FuseboxProperties.POPUP_ATTACH_CLIPBOARD_CLICKED).run());
+        } else if (propertyKey == FuseboxProperties.POPUP_ATTACH_CLIPBOARD_ENABLED) {
+            view.popup.mClipboardButton.setEnabled(
+                    model.get(FuseboxProperties.POPUP_ATTACH_CLIPBOARD_ENABLED));
         } else if (propertyKey == FuseboxProperties.POPUP_ATTACH_CLIPBOARD_VISIBLE) {
             updateButtonVisibility(
                     model,
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxViewBinderUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxViewBinderUnitTest.java
index 3142e50..5eb378e 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxViewBinderUnitTest.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxViewBinderUnitTest.java
@@ -320,6 +320,14 @@
     }
 
     @Test
+    public void testClipboardButtonEnabled() {
+        mModel.set(FuseboxProperties.POPUP_ATTACH_CLIPBOARD_ENABLED, true);
+        assertTrue(mViewHolder.popup.mClipboardButton.isEnabled());
+        mModel.set(FuseboxProperties.POPUP_ATTACH_CLIPBOARD_ENABLED, false);
+        assertFalse(mViewHolder.popup.mClipboardButton.isEnabled());
+    }
+
+    @Test
     public void requestTypeDrawable() {
         mModel.set(
                 FuseboxProperties.AUTOCOMPLETE_REQUEST_TYPE,
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuItemProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuItemProperties.java
index 03f8686a..33283d3b 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuItemProperties.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuItemProperties.java
@@ -20,8 +20,9 @@
 
     public static final WritableObjectPropertyKey<String> TITLE = new WritableObjectPropertyKey<>();
 
-    public static final WritableObjectPropertyKey<View.OnClickListener> CLICK_LISTENER =
-            new WritableObjectPropertyKey<>();
+    public static final WritableObjectPropertyKey<View.OnClickListener>
+            CONTEXT_MENU_BUTTON_ON_CLICK = new WritableObjectPropertyKey<>();
 
-    public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {ICON, TITLE, CLICK_LISTENER};
+    public static final PropertyKey[] ALL_KEYS =
+            new PropertyKey[] {ICON, TITLE, CONTEXT_MENU_BUTTON_ON_CLICK};
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuItemViewBinder.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuItemViewBinder.java
index 70bdebf..9e5270f4 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuItemViewBinder.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuItemViewBinder.java
@@ -33,9 +33,10 @@
                 // TODO: Investigate the correct resizing method.
                 bitmap.setDensity(120);
             }
-        } else if (key == ExtensionsMenuItemProperties.CLICK_LISTENER) {
+        } else if (key == ExtensionsMenuItemProperties.CONTEXT_MENU_BUTTON_ON_CLICK) {
             view.findViewById(R.id.extensions_menu_item_context_menu)
-                    .setOnClickListener(model.get(ExtensionsMenuItemProperties.CLICK_LISTENER));
+                    .setOnClickListener(
+                            model.get(ExtensionsMenuItemProperties.CONTEXT_MENU_BUTTON_ON_CLICK));
         }
     }
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuMediator.java
index 4ecd5a5..db3fa55 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuMediator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuMediator.java
@@ -199,7 +199,7 @@
                     new PropertyModel.Builder(ExtensionsMenuItemProperties.ALL_KEYS)
                             .with(ExtensionsMenuItemProperties.TITLE, entry.actionButton.text)
                             .with(
-                                    ExtensionsMenuItemProperties.CLICK_LISTENER,
+                                    ExtensionsMenuItemProperties.CONTEXT_MENU_BUTTON_ON_CLICK,
                                     (view) ->
                                             onContextMenuButtonClicked(
                                                     (ListMenuButton) view, entry.id))
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuMediatorTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuMediatorTest.java
index 2f5abd1e..6de7598 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuMediatorTest.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuMediatorTest.java
@@ -259,7 +259,7 @@
         // Click on the context menu button.
         ListItem item = mActionModels.get(0);
         View.OnClickListener contextMenuButtonListener =
-                item.model.get(ExtensionsMenuItemProperties.CLICK_LISTENER);
+                item.model.get(ExtensionsMenuItemProperties.CONTEXT_MENU_BUTTON_ON_CLICK);
         ListMenuButton mockContextMenuButton = createMockMenuButton();
         contextMenuButtonListener.onClick(mockContextMenuButton);
 
diff --git a/chrome/browser/ui/ash/projector/projector_client_impl_unittest.cc b/chrome/browser/ui/ash/projector/projector_client_impl_unittest.cc
index 9a813c0..4b56dcb 100644
--- a/chrome/browser/ui/ash/projector/projector_client_impl_unittest.cc
+++ b/chrome/browser/ui/ash/projector/projector_client_impl_unittest.cc
@@ -409,8 +409,7 @@
              features::kForceEnableServerSideSpeechRecognition},
             {features::kInternalServerSideSpeechRecognitionUSMModelFinch}),
         ProjectorClientTestScenario(
-            {features::kInternalServerSideSpeechRecognition,
-             features::kOnDeviceSpeechRecognition},
+            {features::kOnDeviceSpeechRecognition},
             {features::kForceEnableServerSideSpeechRecognition,
              features::kInternalServerSideSpeechRecognitionUSMModelFinch})));
 
diff --git a/chrome/browser/ui/ash/projector/projector_soda_installation_controller_unittest.cc b/chrome/browser/ui/ash/projector/projector_soda_installation_controller_unittest.cc
index c0754d0c..88b72e78 100644
--- a/chrome/browser/ui/ash/projector/projector_soda_installation_controller_unittest.cc
+++ b/chrome/browser/ui/ash/projector/projector_soda_installation_controller_unittest.cc
@@ -53,8 +53,7 @@
     // TODO: dorianbrandon - Remove finch flag from disabled list.
     scoped_feature_list_.InitWithFeatures(
         {features::kOnDeviceSpeechRecognition},
-        {features::kInternalServerSideSpeechRecognition,
-         features::kForceEnableServerSideSpeechRecognition,
+        {features::kForceEnableServerSideSpeechRecognition,
          features::kInternalServerSideSpeechRecognitionUSMModelFinch});
   }
   ProjectorSodaInstallationControllerTest(
@@ -191,7 +190,6 @@
   NewScreencastPrecondition soda_install_error(
       NewScreencastPreconditionState::kDisabled,
       {NewScreencastPreconditionReason::kSodaInstallationErrorUnspecified});
-  EXPECT_CALL(app_client(), OnSodaInstallError());
   EXPECT_CALL(projector_client(),
               OnNewScreencastPreconditionChanged(soda_install_error));
   speech::SodaInstaller::GetInstance()->NotifySodaErrorForTesting(
@@ -204,7 +202,6 @@
   NewScreencastPrecondition soda_install_error(
       NewScreencastPreconditionState::kDisabled,
       {NewScreencastPreconditionReason::kSodaInstallationErrorNeedsReboot});
-  EXPECT_CALL(app_client(), OnSodaInstallError());
   EXPECT_CALL(projector_client(),
               OnNewScreencastPreconditionChanged(soda_install_error));
   speech::SodaInstaller::GetInstance()->NotifySodaErrorForTesting(
diff --git a/chrome/browser/ui/browser_element_identifiers.cc b/chrome/browser/ui/browser_element_identifiers.cc
index c0e4bd9..37b53df 100644
--- a/chrome/browser/ui/browser_element_identifiers.cc
+++ b/chrome/browser/ui/browser_element_identifiers.cc
@@ -66,6 +66,7 @@
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kGlicNudgeButtonElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kGlicActorTaskIconElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kGlicViewElementId);
+DEFINE_ELEMENT_IDENTIFIER_VALUE(kGlicSelectionOverlayViewElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kHatsNextWebDialogId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kHistorySearchInputElementId);
 DEFINE_ELEMENT_IDENTIFIER_VALUE(kInactiveTabSettingElementId);
diff --git a/chrome/browser/ui/browser_element_identifiers.h b/chrome/browser/ui/browser_element_identifiers.h
index efef378..85738f5 100644
--- a/chrome/browser/ui/browser_element_identifiers.h
+++ b/chrome/browser/ui/browser_element_identifiers.h
@@ -106,6 +106,7 @@
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kGlicNudgeButtonElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kGlicActorTaskIconElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kGlicViewElementId);
+DECLARE_ELEMENT_IDENTIFIER_VALUE(kGlicSelectionOverlayViewElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kHistorySearchInputElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kInactiveTabSettingElementId);
 DECLARE_ELEMENT_IDENTIFIER_VALUE(kInstallPwaElementId);
diff --git a/chrome/browser/ui/browser_list.cc b/chrome/browser/ui/browser_list.cc
index 0ff6437..d8053d04 100644
--- a/chrome/browser/ui/browser_list.cc
+++ b/chrome/browser/ui/browser_list.cc
@@ -21,8 +21,6 @@
 #include "chrome/browser/ui/browser_list_enumerator.h"
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
 #include "components/keep_alive_registry/keep_alive_registry.h"
 #include "components/keep_alive_registry/keep_alive_types.h"
 
diff --git a/chrome/browser/ui/browser_list.h b/chrome/browser/ui/browser_list.h
index a8f0e5b..7965efc 100644
--- a/chrome/browser/ui/browser_list.h
+++ b/chrome/browser/ui/browser_list.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/functional/function_ref.h"
+#include "base/gtest_prod_util.h"
 #include "base/lazy_instance.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/raw_ref.h"
@@ -61,6 +62,9 @@
   static void NotifyBrowserNoLongerActive(Browser* browser);
 
  private:
+  friend class BrowserObserverChild;
+  FRIEND_TEST_ALL_PREFIXES(BrowserListBrowserTest, ObserverAddedInFlight);
+
   BrowserList();
   ~BrowserList();
 
diff --git a/chrome/browser/ui/browser_list_browsertest.cc b/chrome/browser/ui/browser_list_browsertest.cc
index aa12ba4..443ee3d 100644
--- a/chrome/browser/ui/browser_list_browsertest.cc
+++ b/chrome/browser/ui/browser_list_browsertest.cc
@@ -82,15 +82,13 @@
  public:
   explicit BrowserObserverChild(Browser* created_for_browser)
       : created_for_browser_(created_for_browser) {
-    ForEachCurrentBrowserWindowInterfaceOrderedByActivation(
-        [this](BrowserWindowInterface* browser) {
-          EXPECT_FALSE(observed_browsers_.contains(browser));
-          observed_browsers_.insert(browser);
-          // TODO(crbug.com/452120900): TabStripModelObserver auto-unregisters
-          // in dtor
-          browser->GetTabStripModel()->AddObserver(this);
-          return true;
-        });
+    for (auto browser : BrowserList::GetInstance()->browsers_) {
+      EXPECT_FALSE(observed_browsers_.contains(browser));
+      observed_browsers_.insert(browser);
+      // TODO(crbug.com/452120900): TabStripModelObserver auto-unregisters
+      // in dtor
+      browser->GetTabStripModel()->AddObserver(this);
+    }
     EXPECT_TRUE(observed_browsers_.contains(created_for_browser_));
     BrowserList::GetInstance()->AddObserver(this);
   }
@@ -139,13 +137,13 @@
 IN_PROC_BROWSER_TEST_F(BrowserListBrowserTest, ObserverAddedInFlight) {
   BrowserObserverParent parent_observer;
 
-  EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
+  EXPECT_EQ(1U, BrowserList::GetInstance()->browsers_.size());
 
   // Adding second browser should not trigger double-observation.
   Browser::Create(Browser::CreateParams(GetProfile(), true));
-  EXPECT_EQ(2U, chrome::GetTotalBrowserCount());
+  EXPECT_EQ(2U, BrowserList::GetInstance()->browsers_.size());
 
   // Create one more browser to trigger BrowserObserverChild::OnBrowserAdded.
   Browser::Create(Browser::CreateParams(GetProfile(), true));
-  EXPECT_EQ(3U, chrome::GetTotalBrowserCount());
+  EXPECT_EQ(3U, BrowserList::GetInstance()->browsers_.size());
 }
diff --git a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskIntegrationTest.java b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskIntegrationTest.java
index 4df7e6c..27a42fe 100644
--- a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskIntegrationTest.java
+++ b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskIntegrationTest.java
@@ -130,6 +130,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "crbug.com/486858979: Temporarily disabled to avoid crashes.")
     public void startWebappActivity_createsChromeAndroidTask() {
         // Act.
         mWebappActivityTestRule.startWebappActivity();
@@ -142,6 +143,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "crbug.com/486858979: Temporarily disabled to avoid crashes.")
     public void startTwa_createsChromeAndroidTask() throws Exception {
         // Act.
         CustomTabActivityTypeTestUtils.launchActivity(
@@ -200,6 +202,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "crbug.com/486858979: Temporarily disabled to avoid crashes.")
     public void startWebappActivity_chromeAndroidTaskAndTabModelHaveSameSessionId() {
         // Arrange.
         mWebappActivityTestRule.startWebappActivity();
@@ -221,6 +224,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest(message = "crbug.com/486858979: Temporarily disabled to avoid crashes.")
     public void startTwa_chromeAndroidTaskAndTabModelHaveSameSessionId() throws Exception {
         // Arrange.
         CustomTabActivityTypeTestUtils.launchActivity(
diff --git a/chrome/browser/ui/lens/lens_overlay_controller.cc b/chrome/browser/ui/lens/lens_overlay_controller.cc
index 3fc79fbc..0962483 100644
--- a/chrome/browser/ui/lens/lens_overlay_controller.cc
+++ b/chrome/browser/ui/lens/lens_overlay_controller.cc
@@ -1499,6 +1499,12 @@
   UpdateEntryPointsState();
 }
 
+bool LensOverlayController::IsOverlayViewShared() const {
+  // The view that host's Lens's WebUI is a direct child of the BrowserView,
+  // which means it can be shared across different tabs.
+  return true;
+}
+
 void LensOverlayController::ActivityRequestedByOverlay(
     ui::mojom::ClickModifiersPtr click_modifiers) {
   // The tab is expected to be in the foreground.
diff --git a/chrome/browser/ui/lens/lens_overlay_controller.h b/chrome/browser/ui/lens/lens_overlay_controller.h
index 7c937691..2123b34 100644
--- a/chrome/browser/ui/lens/lens_overlay_controller.h
+++ b/chrome/browser/ui/lens/lens_overlay_controller.h
@@ -612,6 +612,7 @@
   void NotifyOverlayClosing() override;
   void NotifyTabForegrounded() override;
   void NotifyTabWillEnterBackground() override;
+  bool IsOverlayViewShared() const override;
 
   // content::WebContentsDelegate:
   bool HandleContextMenu(content::RenderFrameHost& render_frame_host,
diff --git a/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc b/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc
index 2bc401f..feb79db 100644
--- a/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc
+++ b/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc
@@ -46,7 +46,9 @@
 constexpr int kTranslateTextTimeoutMs = 500;
 
 LensOverlayUntrustedUI::LensOverlayUntrustedUI(content::WebUI* web_ui)
-    : UntrustedTopChromeWebUIController(web_ui) {
+    : UntrustedTopChromeWebUIController(web_ui,
+                                        /*enable_chrome_send=*/false,
+                                        /*enable_chrome_histograms=*/true) {
   // Set up the chrome-untrusted://lens-overlay source.
   content::WebUIDataSource* html_source =
       content::WebUIDataSource::CreateAndAdd(
diff --git a/chrome/browser/ui/lens/lens_side_panel_untrusted_ui.cc b/chrome/browser/ui/lens/lens_side_panel_untrusted_ui.cc
index c12904f..ceee3079 100644
--- a/chrome/browser/ui/lens/lens_side_panel_untrusted_ui.cc
+++ b/chrome/browser/ui/lens/lens_side_panel_untrusted_ui.cc
@@ -38,7 +38,9 @@
 namespace lens {
 
 LensSidePanelUntrustedUI::LensSidePanelUntrustedUI(content::WebUI* web_ui)
-    : UntrustedTopChromeWebUIController(web_ui) {
+    : UntrustedTopChromeWebUIController(web_ui,
+                                        /*enable_chrome_send=*/false,
+                                        /*enable_chrome_histograms=*/true) {
   // Set up the chrome-untrusted://lens/ source.
   content::WebUIDataSource* html_source =
       content::WebUIDataSource::CreateAndAdd(
diff --git a/chrome/browser/ui/lens/overlay_base_controller.cc b/chrome/browser/ui/lens/overlay_base_controller.cc
index c3993f9..94d58ed 100644
--- a/chrome/browser/ui/lens/overlay_base_controller.cc
+++ b/chrome/browser/ui/lens/overlay_base_controller.cc
@@ -737,11 +737,14 @@
   if (!overlay_view_) {
     return;
   }
-  for (views::View* child : overlay_view_->children()) {
-    if (child->GetVisible()) {
-      // If any child is visible, it is being used by another tab so do not hide
-      // the overlay view.
-      return;
+  // Only check the children's visibilities if the overlay is shared.
+  if (IsOverlayViewShared()) {
+    for (views::View* child : overlay_view_->children()) {
+      if (child->GetVisible()) {
+        // If any child is visible, it is being used by another tab so do not
+        // hide the overlay view.
+        return;
+      }
     }
   }
   overlay_view_->SetVisible(false);
diff --git a/chrome/browser/ui/lens/overlay_base_controller.h b/chrome/browser/ui/lens/overlay_base_controller.h
index 87e08942..e7c8c67 100644
--- a/chrome/browser/ui/lens/overlay_base_controller.h
+++ b/chrome/browser/ui/lens/overlay_base_controller.h
@@ -234,6 +234,9 @@
   // Notification that the tab was foregrounded.
   virtual void NotifyTabWillEnterBackground() = 0;
 
+  // Returns if the overlay view can be shared between multiple tabs.
+  virtual bool IsOverlayViewShared() const = 0;
+
   // If the side panel was closed, we wait for the reflow before beginning
   // the screenshot flow.
   virtual void FinishedWaitingForReflow(base::TimeTicks reflow_start_time);
diff --git a/chrome/browser/ui/omnibox/BUILD.gn b/chrome/browser/ui/omnibox/BUILD.gn
index f8d614b..9e3bc50 100644
--- a/chrome/browser/ui/omnibox/BUILD.gn
+++ b/chrome/browser/ui/omnibox/BUILD.gn
@@ -116,6 +116,7 @@
       "//chrome/browser/favicon",
       "//chrome/browser/history",
       "//chrome/browser/omnibox",
+      "//chrome/browser/predictors",
       "//chrome/browser/preloading",
       "//chrome/browser/preloading/search_preload",
       "//chrome/browser/profiles:profile",
diff --git a/chrome/browser/ui/omnibox/omnibox_context_menu_controller.cc b/chrome/browser/ui/omnibox/omnibox_context_menu_controller.cc
index 02edb23..e2bc6b2 100644
--- a/chrome/browser/ui/omnibox/omnibox_context_menu_controller.cc
+++ b/chrome/browser/ui/omnibox/omnibox_context_menu_controller.cc
@@ -818,6 +818,9 @@
   if (id >= kMinOmniboxContextMenuRecentTabsCommandId &&
       id < kMinOmniboxContextMenuRecentTabsCommandId +
                omnibox::kContextMenuMaxTabSuggestions.Get()) {
+    base::UmaHistogramExactLinear(
+        "ContextualSearch.ContextAdded.ContextAddedMethod.Omnibox",
+        /*ContextMenu*/ 0, 4);
     std::vector<OmniboxContextMenuController::TabInfo> tabs = GetRecentTabs();
     int tab_index_in_menu = id - kMinOmniboxContextMenuRecentTabsCommandId;
     if (static_cast<size_t>(tab_index_in_menu) < tabs.size()) {
diff --git a/chrome/browser/ui/omnibox/omnibox_context_menu_controller_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_context_menu_controller_browsertest.cc
index a004dfb3..31ba1064 100644
--- a/chrome/browser/ui/omnibox/omnibox_context_menu_controller_browsertest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_context_menu_controller_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/omnibox/omnibox_context_menu_controller.h"
 
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -35,6 +36,8 @@
 
 namespace {
 
+constexpr int kMinOmniboxContextMenuRecentTabsCommandId = 33000;
+
 size_t GetVisibleItemCount(const ui::SimpleMenuModel* menu_model) {
   size_t visible_count = 0;
   for (size_t i = 0; i < menu_model->GetItemCount(); i++) {
@@ -181,6 +184,34 @@
   EXPECT_EQ(context->mode, searchbox::mojom::ToolMode::kCreateImage);
 }
 
+IN_PROC_BROWSER_TEST_F(OmniboxContextMenuControllerBrowserTest,
+                       RecordHistogramOnTabSelected) {
+  base::HistogramTester histogram_tester;
+
+  // Navigate the initial tab to the popup URL.
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), GURL(chrome::kChromeUIOmniboxPopupURL)));
+  auto* popup_web_contents = GetWebContents();
+
+  // Add a recent tab.
+  GURL url(embedded_test_server()->GetURL("/title1.html"));
+  ASSERT_TRUE(AddTabAtIndex(1, url, ui::PAGE_TRANSITION_TYPED));
+
+  // The controller should be associated with the popup web contents.
+  auto owning_window = browser()->window()->GetNativeWindow();
+  auto omnibox_popup_file_selector =
+      std::make_unique<OmniboxPopupFileSelector>(owning_window);
+  OmniboxContextMenuController controller(omnibox_popup_file_selector.get(),
+                                          popup_web_contents);
+
+  // The first recent tab item should be at
+  // kMinOmniboxContextMenuRecentTabsCommandId.
+  controller.ExecuteCommand(kMinOmniboxContextMenuRecentTabsCommandId, 0);
+
+  histogram_tester.ExpectUniqueSample(
+      "ContextualSearch.ContextAdded.ContextAddedMethod.Omnibox", 0, 1);
+}
+
 class OmniboxContextMenuControllerBrowserTestWithCommand
     : public OmniboxContextMenuControllerBrowserTest,
       public testing::WithParamInterface<int> {
diff --git a/chrome/browser/ui/promos/ios_promo_controller.cc b/chrome/browser/ui/promos/ios_promo_controller.cc
index c08ae2c1..0cd5f8e5 100644
--- a/chrome/browser/ui/promos/ios_promo_controller.cc
+++ b/chrome/browser/ui/promos/ios_promo_controller.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/promos/ios_promo_controller.h"
 
 #include "base/functional/bind.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -14,9 +15,11 @@
 #include "chrome/browser/ui/promos/ios_promos_utils.h"
 #include "chrome/browser/ui/user_education/browser_user_education_interface.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/common/pref_names.h"
 #include "components/desktop_to_mobile_promos/features.h"
 #include "components/desktop_to_mobile_promos/promos_types.h"
 #include "components/feature_engagement/public/feature_constants.h"
+#include "components/prefs/pref_service.h"
 #include "components/sync_device_info/device_info.h"
 #include "ui/views/widget/widget.h"
 
@@ -68,22 +71,37 @@
   return Get(browser_window_interface->GetUnownedUserDataHost());
 }
 
-void IOSPromoController::OnPromoTriggered(PromoType promo_type) {
+bool IOSPromoController::CanShowIOSPromo(PromoType promo_type) {
+  // TODO(crbug.com/485862381): Remove once check is integrated with user
+  // education system.
+  PrefService* local_state = g_browser_process->local_state();
+  if (local_state && !local_state->GetBoolean(prefs::kPromotionsEnabled)) {
+    return false;
+  }
+
   BrowserWindow* window = browser_->window();
   // Don't show the promo if the toolbar is not visible.
   if (!window || !window->IsToolbarVisible()) {
-    return;
+    return false;
   }
 
   // Do not show the promo if the window is not active.
   BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_);
   if (!browser_view || !browser_view->GetWidget()->ShouldPaintAsActive()) {
-    return;
+    return false;
   }
 
   if (GetMobilePromoOnDesktopForcePromoType() ==
           IOSPromoBubbleForceType::kNoOverride &&
-      !ShouldShowPromo(promo_type)) {
+      !IsUserEligibleForPromo(promo_type)) {
+    return false;
+  }
+
+  return true;
+}
+
+void IOSPromoController::OnPromoTriggered(PromoType promo_type) {
+  if (!CanShowIOSPromo(promo_type)) {
     return;
   }
 
@@ -100,7 +118,7 @@
 // 1. kMobilePromoOnDesktop is enabled AND has a "not very active" iOS device
 // 2. kMobilePromoOnDesktopWithQRCode is enabled AND does not have Chrome
 // installed on any iOS device
-bool IOSPromoController::ShouldShowPromo(PromoType promo_type) {
+bool IOSPromoController::IsUserEligibleForPromo(PromoType promo_type) {
   // Don't show the promo if the user has a recent active Android device.
   if (ios_promos_utils::IsUserActiveOnAndroid(browser_->profile())) {
     return false;
diff --git a/chrome/browser/ui/promos/ios_promo_controller.h b/chrome/browser/ui/promos/ios_promo_controller.h
index 6488a0f..770fb2b 100644
--- a/chrome/browser/ui/promos/ios_promo_controller.h
+++ b/chrome/browser/ui/promos/ios_promo_controller.h
@@ -35,10 +35,13 @@
   static IOSPromoController* From(
       BrowserWindowInterface* browser_window_interface);
 
+  // Returns true if the IOS promos can be shown.
+  bool CanShowIOSPromo(desktop_to_mobile_promos::PromoType promo_type);
+
  private:
   void OnPromoTriggered(desktop_to_mobile_promos::PromoType promo_type);
 
-  bool ShouldShowPromo(desktop_to_mobile_promos::PromoType promo_type);
+  bool IsUserEligibleForPromo(desktop_to_mobile_promos::PromoType promo_type);
 
   const raw_ptr<Browser> browser_;
 
diff --git a/chrome/browser/ui/read_anything/read_anything_controller.cc b/chrome/browser/ui/read_anything/read_anything_controller.cc
index aeb685d..6ed21c05 100644
--- a/chrome/browser/ui/read_anything/read_anything_controller.cc
+++ b/chrome/browser/ui/read_anything/read_anything_controller.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/read_anything/read_anything_controller.h"
 
 #include "base/functional/bind.h"
+#include "base/metrics/histogram_functions.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window/public/browser_window_features.h"
@@ -296,6 +297,9 @@
   // Reading Mode was inactive.
   if (distillation_state_ == DistillationState::kDistillationEmpty &&
       GetPresentationState() == PresentationState::kInactive) {
+    base::UmaHistogramEnumeration(
+        "Accessibility.ReadAnything.SidePanelTriggeredByEmptyState", trigger);
+
     SidePanelOpenTrigger side_panel_open_trigger =
         read_anything::ReadAnythingToSidePanelOpenTrigger(trigger);
 
@@ -462,6 +466,10 @@
 
   if (new_state == DistillationState::kDistillationEmpty &&
       GetPresentationState() == PresentationState::kInImmersiveOverlay) {
+    base::UmaHistogramEnumeration(
+        "Accessibility.ReadAnything.SidePanelTriggeredByEmptyState",
+        ReadAnythingOpenTrigger::kReadAnythingTogglePresentationButton);
+
     TogglePresentation();
   }
   distillation_state_ = new_state;
diff --git a/chrome/browser/ui/read_anything/read_anything_controller_browsertest.cc b/chrome/browser/ui/read_anything/read_anything_controller_browsertest.cc
index b730092..0c0b5722 100644
--- a/chrome/browser/ui/read_anything/read_anything_controller_browsertest.cc
+++ b/chrome/browser/ui/read_anything/read_anything_controller_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/read_anything/read_anything_controller.h"
 
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/run_until.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -1386,6 +1387,7 @@
 IN_PROC_BROWSER_TEST_F(
     ReadAnythingControllerBrowserTest,
     OnDistillationStateChanged_EmptyContentInImmersive_TogglesToSidePanel) {
+  base::HistogramTester histogram_tester;
   tabs::TabInterface* tab = browser()->tab_strip_model()->GetActiveTab();
   ASSERT_TRUE(tab);
   auto* controller = ReadAnythingController::From(tab);
@@ -1408,6 +1410,10 @@
     return side_panel_ui->IsSidePanelEntryShowing(
         SidePanelEntryKey(SidePanelEntryId::kReadAnything));
   }));
+
+  histogram_tester.ExpectUniqueSample(
+      "Accessibility.ReadAnything.SidePanelTriggeredByEmptyState",
+      ReadAnythingOpenTrigger::kReadAnythingTogglePresentationButton, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(
@@ -1466,6 +1472,7 @@
 IN_PROC_BROWSER_TEST_F(
     ReadAnythingControllerBrowserTest,
     OnDistillationStateChanged_OpenWithDistillationEmpty_OpensInSidePanel) {
+  base::HistogramTester histogram_tester;
   tabs::TabInterface* tab = browser()->tab_strip_model()->GetActiveTab();
   ASSERT_TRUE(tab);
   auto* controller = ReadAnythingController::From(tab);
@@ -1496,6 +1503,10 @@
     return side_panel_ui->IsSidePanelEntryShowing(
         SidePanelEntryKey(SidePanelEntryId::kReadAnything));
   }));
+
+  histogram_tester.ExpectUniqueSample(
+      "Accessibility.ReadAnything.SidePanelTriggeredByEmptyState",
+      ReadAnythingOpenTrigger::kOmniboxChip, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(
diff --git a/chrome/browser/ui/read_anything/read_anything_omnibox_controller.cc b/chrome/browser/ui/read_anything/read_anything_omnibox_controller.cc
index 98930125..d698565 100644
--- a/chrome/browser/ui/read_anything/read_anything_omnibox_controller.cc
+++ b/chrome/browser/ui/read_anything/read_anything_omnibox_controller.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/dom_distiller/tab_utils.h"
 #include "chrome/browser/ui/actions/chrome_action_id.h"
 #include "chrome/browser/ui/read_anything/read_anything_controller.h"
+#include "chrome/browser/ui/read_anything/read_anything_enums.h"
 #include "chrome/browser/ui/read_anything/read_anything_side_panel_controller_utils.h"
 #include "chrome/browser/ui/tabs/public/tab_features.h"
 #include "chrome/browser/ui/ui_features.h"
@@ -76,7 +77,12 @@
 
     if (features::IsReadAnythingOmniboxChipEnabled() &&
         base::FeatureList::IsEnabled(features::kPageActionsMigration) &&
-        open_trigger.has_value() && GetCurrentPageActionState().showing) {
+        open_trigger.has_value() &&
+        open_trigger.value() !=
+            ReadAnythingOpenTrigger::kReadAnythingTogglePresentationButton &&
+        GetCurrentPageActionState().showing) {
+      // Ignore the toggle presentation button for this metric, since that can
+      // only be used after RM is already open.
       base::UmaHistogramEnumeration(
           "Accessibility.ReadAnything.EntryPointAfterOmnibox",
           open_trigger.value());
diff --git a/chrome/browser/ui/read_anything/read_anything_omnibox_controller_browsertest.cc b/chrome/browser/ui/read_anything/read_anything_omnibox_controller_browsertest.cc
index 64759e4..0203b4d 100644
--- a/chrome/browser/ui/read_anything/read_anything_omnibox_controller_browsertest.cc
+++ b/chrome/browser/ui/read_anything/read_anything_omnibox_controller_browsertest.cc
@@ -161,3 +161,19 @@
       "Accessibility.ReadAnything.EntryPointAfterOmnibox",
       ReadAnythingOpenTrigger::kReadAnythingContextMenu, 1);
 }
+
+IN_PROC_BROWSER_TEST_F(ReadAnythingOmniboxControllerBrowserTest,
+                       Activate_DoesNotLogTogglePresentationAfterOmniboxShown) {
+  base::HistogramTester histogram_tester;
+  controller_ = CreateController();
+
+  tabs::TabInterface* tab = browser()->tab_strip_model()->GetActiveTab();
+  tab->GetTabFeatures()->page_action_controller()->Show(
+      kActionSidePanelShowReadAnything);
+
+  controller_->Activate(
+      true, ReadAnythingOpenTrigger::kReadAnythingTogglePresentationButton);
+
+  histogram_tester.ExpectTotalCount(
+      "Accessibility.ReadAnything.EntryPointAfterOmnibox", 0);
+}
diff --git a/chrome/browser/ui/tabs/BUILD.gn b/chrome/browser/ui/tabs/BUILD.gn
index 3200e7d..3c8c3e88 100644
--- a/chrome/browser/ui/tabs/BUILD.gn
+++ b/chrome/browser/ui/tabs/BUILD.gn
@@ -519,7 +519,6 @@
       "//chrome/browser/contextual_cueing",
       "//chrome/browser/contextual_tasks",
       "//chrome/browser/favicon",
-      "//chrome/browser/glic/selection",
       "//chrome/browser/image_fetcher",
       "//chrome/browser/indigo",
       "//chrome/browser/media/webrtc",
@@ -601,6 +600,9 @@
 
     if (enable_glic) {
       deps += [ "//chrome/browser/glic" ]
+      if (!is_android) {
+        deps += [ "//chrome/browser/glic/selection" ]
+      }
     }
 
     if (!is_android) {
diff --git a/chrome/browser/ui/tabs/tab_dialog_manager.cc b/chrome/browser/ui/tabs/tab_dialog_manager.cc
index ed1c989..d43f108 100644
--- a/chrome/browser/ui/tabs/tab_dialog_manager.cc
+++ b/chrome/browser/ui/tabs/tab_dialog_manager.cc
@@ -336,7 +336,8 @@
           constrained_window::kConstrainedWindowWidgetIdentifier));
   if (params_->disable_input) {
     scoped_ignore_input_events_ =
-        tab_interface_->GetContents()->IgnoreInputEvents(std::nullopt);
+        tab_interface_->GetContents()->IgnoreInputEvents(
+            std::nullopt, /*should_ignore_a11y_input=*/true);
     tab_interface_->GetBrowserWindowInterface()
         ->capabilities()
         ->SetWebContentsBlocked(tab_interface_->GetContents(),
diff --git a/chrome/browser/ui/views/autofill/popup/popup_view_views_unittest.cc b/chrome/browser/ui/views/autofill/popup/popup_view_views_unittest.cc
index 627ad0a..c7802c7 100644
--- a/chrome/browser/ui/views/autofill/popup/popup_view_views_unittest.cc
+++ b/chrome/browser/ui/views/autofill/popup/popup_view_views_unittest.cc
@@ -33,6 +33,7 @@
 #include "chrome/browser/ui/views/autofill/popup/popup_view_utils.h"
 #include "chrome/browser/ui/views/autofill/popup/popup_view_views_test_api.h"
 #include "chrome/browser/ui/views/autofill/popup/popup_warning_view.h"
+#include "chrome/test/base/chrome_test_utils.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/views/chrome_views_test_base.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics.h"
@@ -1815,7 +1816,12 @@
 // environment (namely creates a `TestingProfile`) that fails to be created in
 // the sub-process (see `EXPECT_CHECK_DEATH_WITH` doc for details). This fail
 // hides the real death reason to be tested.
-using PopupViewViewsDeathTest = ChromeViewsTestBase;
+class PopupViewViewsDeathTest
+    : public chrome_test_utils::TestingBrowserProcessDeathTestMixin,
+      public ChromeViewsTestBase {
+  using ChromeViewsTestBase::ChromeViewsTestBase;
+};
+
 TEST_F(PopupViewViewsDeathTest, OpenSubPopupWithNoChildrenCheckCrash) {
   NiceMock<MockAutofillPopupController> controller;
   controller.set_suggestions({
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
index fd3ca1f..c754612 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
@@ -28,6 +28,9 @@
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/page_action/page_action_icon_type.h"
+#include "chrome/browser/ui/promos/ios_promo_controller.h"
+#include "chrome/browser/ui/promos/ios_promo_trigger_service.h"
+#include "chrome/browser/ui/promos/ios_promo_trigger_service_factory.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/user_education/browser_user_education_interface.h"
 #include "chrome/browser/ui/views/commerce/price_tracking_email_dialog_view.h"
@@ -43,6 +46,8 @@
 #include "components/commerce/core/metrics/metrics_utils.h"
 #include "components/commerce/core/price_tracking_utils.h"
 #include "components/commerce/core/shopping_service.h"
+#include "components/desktop_to_mobile_promos/features.h"
+#include "components/desktop_to_mobile_promos/promos_types.h"
 #include "components/feature_engagement/public/feature_constants.h"
 #include "components/feature_engagement/public/tracker.h"
 #include "components/image_fetcher/core/image_fetcher.h"
@@ -129,13 +134,45 @@
   return centered_favicon;
 }
 
-base::OnceCallback<void()> CreatePriceTrackingEmailCallback(
+bool ShouldShowIOSPriceTrackingPromo(content::WebContents* web_contents,
+                                     Browser* browser) {
+  auto* const interface =
+      BrowserUserEducationInterface::MaybeGetForWebContentsInTab(web_contents);
+  IOSPromoController* controller = IOSPromoController::From(browser);
+  return ((interface &&
+           interface->CanShowFeaturePromo(
+               feature_engagement::kIPHiOSPriceTrackingDesktopFeature)) &&
+          (controller &&
+           controller->CanShowIOSPromo(
+               desktop_to_mobile_promos::PromoType::kPriceTracking)) &&
+          (MobilePromoOnDesktopTypeEnabled(
+              MobilePromoOnDesktopPromoType::kPriceTracking)));
+}
+
+base::OnceCallback<void()> CreatePriceTrackingCallback(
+    Browser* browser,
     Profile* profile,
     views::View* anchor_view,
     content::WebContents* web_contents,
     const bookmarks::BookmarkNode* bookmark) {
-  if (!profile ||
-      commerce::IsEmailNotificationPrefSetByUser(profile->GetPrefs())) {
+  if (!profile) {
+    return base::DoNothing();
+  }
+
+  // If it is eligible, the Desktop to Mobile Price Tracking promo should
+  // replace the email promo because they have the same alerting purpose.
+  if (ShouldShowIOSPriceTrackingPromo(web_contents, browser)) {
+    IOSPromoTriggerService* const trigger_service =
+        IOSPromoTriggerServiceFactory::GetForProfile(profile);
+    if (trigger_service) {
+      return base::BindOnce(
+          &IOSPromoTriggerService::NotifyPromoShouldBeShown,
+          base::Unretained(trigger_service),
+          desktop_to_mobile_promos::PromoType::kPriceTracking);
+    }
+  }
+
+  if (commerce::IsEmailNotificationPrefSetByUser(profile->GetPrefs())) {
     return base::DoNothing();
   }
 
@@ -409,9 +446,8 @@
   commerce::ShoppingService* shopping_service =
       commerce::ShoppingServiceFactory::GetForBrowserContext(profile);
 
-  base::OnceCallback<void()> post_save_callback =
-      CreatePriceTrackingEmailCallback(profile, anchor_view, web_contents,
-                                       bookmark_node);
+  base::OnceCallback<void()> post_save_callback = CreatePriceTrackingCallback(
+      browser, profile, anchor_view, web_contents, bookmark_node);
 
   auto bubble_delegate_unique =
       std::make_unique<BookmarkBubbleDelegate>(browser, url);
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 8b2484ba..c9700a0 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -124,6 +124,8 @@
 struct WebAppBannerData;
 }  // namespace webapps
 
+class CustomFloatingCorner;
+
 ///////////////////////////////////////////////////////////////////////////////
 // BrowserView
 //
@@ -1306,8 +1308,8 @@
   raw_ptr<VerticalTabStripRegionView> vertical_tab_strip_region_view_ = nullptr;
 
   // Outward-projecting corners of the vertical tab strip.
-  raw_ptr<views::View> vertical_tab_strip_top_corner_ = nullptr;
-  raw_ptr<views::View> vertical_tab_strip_bottom_corner_ = nullptr;
+  raw_ptr<CustomFloatingCorner> vertical_tab_strip_top_corner_ = nullptr;
+  raw_ptr<CustomFloatingCorner> vertical_tab_strip_bottom_corner_ = nullptr;
 
   // The view responsible for housing the contents of the projects panel.
   raw_ptr<ProjectsPanelView> projects_panel_container_ = nullptr;
diff --git a/chrome/browser/ui/views/frame/contents_container_view.cc b/chrome/browser/ui/views/frame/contents_container_view.cc
index c7395e8..290f565d 100644
--- a/chrome/browser/ui/views/frame/contents_container_view.cc
+++ b/chrome/browser/ui/views/frame/contents_container_view.cc
@@ -122,6 +122,17 @@
   }
 
 #if BUILDFLAG(ENABLE_GLIC)
+  if (base::FeatureList::IsEnabled(features::kGlicRegionSelectionNew)) {
+    auto glic_selection_overlay_view = std::make_unique<views::WebView>();
+    glic_selection_overlay_view->SetProperty(
+        views::kElementIdentifierKey, kGlicSelectionOverlayViewElementId);
+    glic_selection_overlay_view->SetVisible(false);
+    glic_selection_overlay_view->SetLayoutManager(
+        std::make_unique<views::FillLayout>());
+    glic_selection_overlay_view_ =
+        AddChildView(std::move(glic_selection_overlay_view));
+  }
+
   if (glic::GlicEnabling::IsProfileEligible(browser_view->GetProfile())) {
     glic_border_ = AddChildView(
         views::Builder<glic::ContextSharingBorderView>(
@@ -269,6 +280,10 @@
   }
 
 #if BUILDFLAG(ENABLE_GLIC)
+  if (glic_selection_overlay_view_) {
+    glic_selection_overlay_view_->holder()->SetCornerRadii(radii);
+  }
+
   if (glic_border_) {
     glic_border_->SetRoundedCorners(content_rounded_corners);
   }
@@ -295,6 +310,10 @@
   }
 
 #if BUILDFLAG(ENABLE_GLIC)
+  if (glic_selection_overlay_view_) {
+    glic_selection_overlay_view_->holder()->SetCornerRadii(kNoRoundedCorners);
+  }
+
   if (glic_border_) {
     glic_border_->SetRoundedCorners(kNoRoundedCorners);
   }
@@ -610,6 +629,15 @@
         non_devtools_contents_bounds, size_bounds);
   }
 
+#if BUILDFLAG(ENABLE_GLIC)
+  if (glic_selection_overlay_view_) {
+    layouts.child_layouts.emplace_back(
+        glic_selection_overlay_view_.get(),
+        glic_selection_overlay_view_->GetVisible(),
+        non_devtools_contents_bounds, size_bounds);
+  }
+#endif
+
   // Reading Mode overlay view bounds are the same as the contents view.
   if (features::IsImmersiveReadAnythingEnabled() &&
       read_anything_immersive_overlay_view_) {
diff --git a/chrome/browser/ui/views/frame/contents_container_view.h b/chrome/browser/ui/views/frame/contents_container_view.h
index 5ce0822..d749e3c 100644
--- a/chrome/browser/ui/views/frame/contents_container_view.h
+++ b/chrome/browser/ui/views/frame/contents_container_view.h
@@ -195,6 +195,10 @@
   // overlay that is shown on top of the web contents.
   raw_ptr<ActorOverlayWebView> actor_overlay_web_view_ = nullptr;
 
+  // Contains glic selection overlay. The overlay renders a static screenshot
+  // of the WebContents and is drawn on top of the WebContents.
+  raw_ptr<views::WebView> glic_selection_overlay_view_ = nullptr;
+
   // The glic browser view that renders around the web contents area.
   raw_ptr<glic::ContextSharingBorderView> glic_border_ = nullptr;
 
diff --git a/chrome/browser/ui/views/frame/custom_corners.cc b/chrome/browser/ui/views/frame/custom_corners.cc
index 722fb6d..3de5f32 100644
--- a/chrome/browser/ui/views/frame/custom_corners.cc
+++ b/chrome/browser/ui/views/frame/custom_corners.cc
@@ -34,33 +34,68 @@
                               base::Unretained(this)));
 }
 
+void CustomCorners::SetFadeBackground(
+    std::optional<FadeBackground> fade_background) {
+  if (fade_background_ == fade_background) {
+    return;
+  }
+
+  fade_background_ = std::move(fade_background);
+  SchedulePaintHost();
+}
+
 void CustomCorners::PaintPath(gfx::Canvas* canvas,
                               const SkPath& path,
                               ColorChoice color_choice,
                               bool anti_alias) const {
-  if (std::holds_alternative<ToolbarTheme>(color_choice)) {
-    gfx::ScopedCanvas scoped(canvas);
-    canvas->ClipPath(path, anti_alias);
-    ThemedBackground::PaintBackground(
-        canvas, &GetView(), &browser_view(),
-        ThemedBackground::ThemeChoice::kToolbarTheme);
+  auto paint_color = [&](ColorChoice choice, float alpha) {
+    if (std::holds_alternative<ToolbarTheme>(choice) ||
+        std::holds_alternative<FrameTheme>(choice)) {
+      gfx::ScopedCanvas scoped(canvas);
+      canvas->ClipPath(path, anti_alias);
+      // If this theme color should have any transparency, we paint it to a
+      // layer so we can adjust the layer's transparency.
+      bool has_transparency = alpha < 1.0f;
+      if (has_transparency) {
+        cc::PaintFlags layer_flags;
+        layer_flags.setAlphaf(alpha);
+        canvas->SaveLayerWithFlags(layer_flags);
+      }
+      ThemedBackground::PaintBackground(
+          canvas, &GetView(), &browser_view(),
+          std::holds_alternative<ToolbarTheme>(choice)
+              ? ThemedBackground::ThemeChoice::kToolbarTheme
+              : ThemedBackground::ThemeChoice::kFrameTheme);
+    } else {
+      ui::ColorId color_id = std::get<ui::ColorId>(choice);
+
+      cc::PaintFlags flags;
+      flags.setAntiAlias(anti_alias);
+      flags.setStyle(cc::PaintFlags::kFill_Style);
+      flags.setColor(
+          SkColorSetA(GetView().GetColorProvider()->GetColor(color_id),
+                      std::clamp(static_cast<int>(255 * alpha), 0, 255)));
+      canvas->DrawPath(path, flags);
+    }
+  };
+
+  // A fade background may be drawn with some transparency over the original
+  // background. If the fade background is fully transparent, we only draw the
+  // original background. If the fade background is fully opaque, we only draw
+  // the fade background. If the fade background is partially transparent, we
+  // draw the original background at full opacity with the partially transparent
+  // fade background on top.
+  if (fade_background_.has_value()) {
+    if (fade_background_->opacity <= 0.0f) {
+      paint_color(color_choice, 1.0f);
+    } else if (fade_background_->opacity < 1.0f) {
+      paint_color(color_choice, 1.0f);
+      paint_color(fade_background_->color, fade_background_->opacity);
+    } else {
+      paint_color(fade_background_->color, 1.0f);
+    }
     return;
   }
 
-  if (std::holds_alternative<FrameTheme>(color_choice)) {
-    gfx::ScopedCanvas scoped(canvas);
-    canvas->ClipPath(path, anti_alias);
-    ThemedBackground::PaintBackground(
-        canvas, &GetView(), &browser_view(),
-        ThemedBackground::ThemeChoice::kFrameTheme);
-    return;
-  }
-
-  ui::ColorVariant color = std::get<ui::ColorId>(color_choice);
-
-  cc::PaintFlags flags;
-  flags.setAntiAlias(anti_alias);
-  flags.setStyle(cc::PaintFlags::kFill_Style);
-  flags.setColor(color.ResolveToSkColor(GetView().GetColorProvider()));
-  canvas->DrawPath(path, flags);
+  paint_color(color_choice, 1.0f);
 }
diff --git a/chrome/browser/ui/views/frame/custom_corners.h b/chrome/browser/ui/views/frame/custom_corners.h
index e2d7f0a..5aae67b 100644
--- a/chrome/browser/ui/views/frame/custom_corners.h
+++ b/chrome/browser/ui/views/frame/custom_corners.h
@@ -5,6 +5,9 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_FRAME_CUSTOM_CORNERS_H_
 #define CHROME_BROWSER_UI_VIEWS_FRAME_CUSTOM_CORNERS_H_
 
+#include <optional>
+#include <variant>
+
 #include "base/callback_list.h"
 #include "base/memory/raw_ref.h"
 #include "base/scoped_observation.h"
@@ -29,10 +32,25 @@
   // Specifies which color to be used for the background.
   using ColorChoice = std::variant<FrameTheme, ToolbarTheme, ui::ColorId>;
 
+  // Background to be overlaid on the corner's original background.
+  struct FadeBackground {
+    // Specifies which color to be used for the fade background.
+    ColorChoice color;
+    // Specifies the opacity to be used for the fade background, with 0.0 being
+    // fully transparent and 1.0 being fully opaque.
+    float opacity;
+
+    bool operator==(const FadeBackground& other) const = default;
+  };
+
   CustomCorners(const CustomCorners&) = delete;
   void operator=(const CustomCorners&) = delete;
   ~CustomCorners() override;
 
+  // Fades the background of the region to `fade_background`. If
+  // `fade_background` is nullopt, then the fade is removed.
+  void SetFadeBackground(std::optional<FadeBackground> fade_background);
+
  protected:
   explicit CustomCorners(BrowserView&);
 
@@ -44,6 +62,9 @@
   // Handle the case where the browser's paint-as-active state changes.
   virtual void OnBrowserPaintAsActiveChanged() = 0;
 
+  // Schedule a paint on the host view.
+  virtual void SchedulePaintHost() = 0;
+
   // Paints the given `path` on `canvas` using `color_choice`.
   void PaintPath(gfx::Canvas* canvas,
                  const SkPath& path,
@@ -58,6 +79,9 @@
   base::ScopedObservation<views::View, views::ViewObserver>
       browser_view_observation_{this};
   base::CallbackListSubscription browser_paint_as_active_subscription_;
+
+  // Background to be overlaid on the corner's original background.
+  std::optional<FadeBackground> fade_background_;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_FRAME_CUSTOM_CORNERS_H_
diff --git a/chrome/browser/ui/views/frame/custom_corners_background.cc b/chrome/browser/ui/views/frame/custom_corners_background.cc
index daf719e..7c6f2e02 100644
--- a/chrome/browser/ui/views/frame/custom_corners_background.cc
+++ b/chrome/browser/ui/views/frame/custom_corners_background.cc
@@ -293,6 +293,10 @@
   }
 }
 
+void CustomCornersBackground::SchedulePaintHost() {
+  view_->SchedulePaint();
+}
+
 CustomCornersBackground::Corners CustomCornersBackground::GetMirroredCorners()
     const {
   Corners corners = corners_;
diff --git a/chrome/browser/ui/views/frame/custom_corners_background.h b/chrome/browser/ui/views/frame/custom_corners_background.h
index 12695c19..4c243e3 100644
--- a/chrome/browser/ui/views/frame/custom_corners_background.h
+++ b/chrome/browser/ui/views/frame/custom_corners_background.h
@@ -101,6 +101,7 @@
   // CustomCorners:
   const views::View& GetView() const override;
   void OnBrowserPaintAsActiveChanged() override;
+  void SchedulePaintHost() override;
 
   int default_radius() const { return default_radius_; }
 
diff --git a/chrome/browser/ui/views/frame/custom_floating_corner.cc b/chrome/browser/ui/views/frame/custom_floating_corner.cc
index f199157..7846c94 100644
--- a/chrome/browser/ui/views/frame/custom_floating_corner.cc
+++ b/chrome/browser/ui/views/frame/custom_floating_corner.cc
@@ -272,5 +272,9 @@
   }
 }
 
+void CustomFloatingCorner::SchedulePaintHost() {
+  SchedulePaint();
+}
+
 BEGIN_METADATA(CustomFloatingCorner)
 END_METADATA
diff --git a/chrome/browser/ui/views/frame/custom_floating_corner.h b/chrome/browser/ui/views/frame/custom_floating_corner.h
index d8e716dc..75b78ca 100644
--- a/chrome/browser/ui/views/frame/custom_floating_corner.h
+++ b/chrome/browser/ui/views/frame/custom_floating_corner.h
@@ -71,6 +71,7 @@
   // CustomCorners:
   const views::View& GetView() const override;
   void OnBrowserPaintAsActiveChanged() override;
+  void SchedulePaintHost() override;
 
   CornerOrientation orientation_;
   views::ShapeContextTokens corner_radius_token_;
diff --git a/chrome/browser/ui/views/frame/horizontal_tab_strip_region_view.cc b/chrome/browser/ui/views/frame/horizontal_tab_strip_region_view.cc
index 5936677..ddeada6 100644
--- a/chrome/browser/ui/views/frame/horizontal_tab_strip_region_view.cc
+++ b/chrome/browser/ui/views/frame/horizontal_tab_strip_region_view.cc
@@ -78,6 +78,10 @@
 #include "ui/aura/window.h"
 #endif
 
+#if BUILDFLAG(IS_MAC)
+constexpr int kTabStripRegionInternalPaddingMac = 12;
+#endif
+
 namespace {
 
 class FrameGrabHandle : public views::View {
@@ -235,9 +239,6 @@
         AddChildView(std::make_unique<TabStripComboButton>(browser));
     combo_button_->SetProperty(views::kCrossAxisAlignmentKey,
                                views::LayoutAlignment::kCenter);
-    combo_button_->SetPaintToLayer();
-    combo_button_->layer()->SetFillsBoundsOpaquely(false);
-    combo_button_->SetProperty(views::kViewIgnoredByLayoutKey, true);
   }
 
   if (base::FeatureList::IsEnabled(features::kTabGroupsFocusing)) {
@@ -685,6 +686,24 @@
   return tab_strip_;
 }
 
+bool HorizontalTabStripRegionView::HasLeadingButtons() const {
+  if (combo_button_ && combo_button_->GetVisible() &&
+      ((combo_button_->start_button() &&
+        combo_button_->start_button()->GetVisible()) ||
+       (combo_button_->end_button() &&
+        combo_button_->end_button()->GetVisible()))) {
+    return true;
+  }
+  if (unfocus_button_ && unfocus_button_->GetVisible()) {
+    return true;
+  }
+  if (tab_search_container_ && render_tab_search_before_tab_strip_ &&
+      tab_search_container_->GetVisible()) {
+    return true;
+  }
+  return false;
+}
+
 void HorizontalTabStripRegionView::LogTabSearchPositionForTesting() {
   tab_search_position_metrics_logger_->LogMetricsForTesting();  // IN-TEST
 }
@@ -741,6 +760,17 @@
 }
 
 void HorizontalTabStripRegionView::UpdateTabStripMargin() {
+#if BUILDFLAG(IS_MAC)
+  if (HasLeadingButtons()) {
+    // When leading buttons are present, maintain a consistent 12px gap from
+    // the caption buttons on Mac.
+    SetProperty(views::kInternalPaddingKey,
+                gfx::Insets::TLBR(0, kTabStripRegionInternalPaddingMac, 0, 0));
+  } else {
+    ClearProperty(views::kInternalPaddingKey);
+  }
+#endif
+
   // The new tab button overlaps the tabstrip. Render it to a layer and adjust
   // the tabstrip right margin to reserve space for it.
   std::optional<int> tab_strip_right_margin;
@@ -781,6 +811,9 @@
   }
 
   if (combo_button_) {
+    combo_button_->SetPaintToLayer();
+    combo_button_->layer()->SetFillsBoundsOpaquely(false);
+    combo_button_->SetProperty(views::kViewIgnoredByLayoutKey, true);
     current_leading_width +=
         combo_button_->GetPreferredSize().width() +
         GetLayoutConstant(LayoutConstant::kTabStripPadding);
diff --git a/chrome/browser/ui/views/frame/horizontal_tab_strip_region_view.h b/chrome/browser/ui/views/frame/horizontal_tab_strip_region_view.h
index 88cc637..dd70454 100644
--- a/chrome/browser/ui/views/frame/horizontal_tab_strip_region_view.h
+++ b/chrome/browser/ui/views/frame/horizontal_tab_strip_region_view.h
@@ -138,6 +138,7 @@
   void SetTabStripObserver(TabStripObserver* observer) override;
   views::View* GetTabStripView() override;
 
+  bool HasLeadingButtons() const;
   void LogTabSearchPositionForTesting();
 
  private:
diff --git a/chrome/browser/ui/views/frame/horizontal_tab_strip_region_view_browsertest.cc b/chrome/browser/ui/views/frame/horizontal_tab_strip_region_view_browsertest.cc
index 51b229f..d73bcf96 100644
--- a/chrome/browser/ui/views/frame/horizontal_tab_strip_region_view_browsertest.cc
+++ b/chrome/browser/ui/views/frame/horizontal_tab_strip_region_view_browsertest.cc
@@ -246,6 +246,17 @@
   EXPECT_TRUE(ax_node_data.HasState(ax::mojom::State::kMultiselectable));
 }
 
+IN_PROC_BROWSER_TEST_F(HorizontalTabStripRegionViewTest,
+                       IncognitoLeadingButtonsCheckDoesntCrash) {
+  Browser* incognito_browser = CreateIncognitoBrowser();
+  HorizontalTabStripRegionView* incognito_tab_strip_region_view =
+      views::AsViewClass<HorizontalTabStripRegionView>(
+          BrowserView::GetBrowserViewForBrowser(incognito_browser)
+              ->tab_strip_view());
+  // This should not crash.
+  incognito_tab_strip_region_view->HasLeadingButtons();
+}
+
 // When scrolling is disabled, the tab strip cannot be larger than the container
 // so tabs that do not fit in the tabstrip will become invisible. This is the
 // opposite behavior from
diff --git a/chrome/browser/ui/views/frame/layout/browser_view_layout.h b/chrome/browser/ui/views/frame/layout/browser_view_layout.h
index 253d2c2..1fbb00b6 100644
--- a/chrome/browser/ui/views/frame/layout/browser_view_layout.h
+++ b/chrome/browser/ui/views/frame/layout/browser_view_layout.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/memory/raw_ptr.h"
+#include "chrome/browser/ui/views/frame/custom_floating_corner.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/native_ui_types.h"
@@ -58,8 +59,8 @@
   raw_ptr<HorizontalTabStripRegionView> horizontal_tab_strip_region_view =
       nullptr;
   raw_ptr<VerticalTabStripRegionView> vertical_tab_strip_region_view = nullptr;
-  raw_ptr<views::View> vertical_tab_strip_bottom_corner = nullptr;
-  raw_ptr<views::View> vertical_tab_strip_top_corner = nullptr;
+  raw_ptr<CustomFloatingCorner> vertical_tab_strip_bottom_corner = nullptr;
+  raw_ptr<CustomFloatingCorner> vertical_tab_strip_top_corner = nullptr;
   raw_ptr<ProjectsPanelView> projects_panel_container = nullptr;
   raw_ptr<views::View> toolbar = nullptr;
   raw_ptr<InfoBarContainerView> infobar_container = nullptr;
diff --git a/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.cc b/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.cc
index c6b082e..be53647 100644
--- a/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.cc
+++ b/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.cc
@@ -34,6 +34,7 @@
 #include "ui/gfx/geometry/outsets.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/views/controls/separator.h"
+#include "ui/views/view_class_properties.h"
 #include "ui/views/view_utils.h"
 
 #if BUILDFLAG(IS_MAC)
@@ -130,6 +131,26 @@
   return TopSeparatorType::kMultiContents;
 }
 
+// Inset the leading edge of the tabstrip by the size of the swoop of the
+// first tab; this is especially important for Mac, where the negative
+// space of the caption button margins and the edge of the tabstrip should
+// overlap. This only applies if there are no other leading buttons; if
+// there are, we want a consistent gap from the caption buttons. The
+// trailing edge receives the usual treatment, as it is the new tab button
+// and not a tab.
+int BrowserViewTabbedLayoutImpl::GetHorizontalTabStripLeadingMargin(
+    const BrowserLayoutParams& params) const {
+  int leading_margin = TabStyle::Get()->GetBottomCornerRadius();
+  if (const gfx::Insets* internal_padding =
+          views().horizontal_tab_strip_region_view->GetProperty(
+              views::kInternalPaddingKey)) {
+    leading_margin =
+        std::max(0.f, params.leading_exclusion.horizontal_padding -
+                          static_cast<float>(internal_padding->left()));
+  }
+  return leading_margin;
+}
+
 std::pair<gfx::Size, gfx::Size>
 BrowserViewTabbedLayoutImpl::GetMinimumTabStripSize(
     const BrowserLayoutParams& params) const {
@@ -570,14 +591,9 @@
                    views().browser_view)) {
     gfx::Rect tabstrip_bounds;
     if (tab_strip_type == TabStripType::kHorizontal) {
-      // Inset the leading edge of the tabstrip by the size of the swoop of the
-      // first tab; this is especially important for Mac, where the negative
-      // space of the caption button margins and the edge of the tabstrip should
-      // overlap. The trailing edge receives the usual treatment, as it is the
-      // new tab button and not a tab.
+      const int leading_margin = GetHorizontalTabStripLeadingMargin(params);
       tabstrip_bounds = GetBoundsWithExclusion(
-          params, views().horizontal_tab_strip_region_view,
-          TabStyle::Get()->GetBottomCornerRadius());
+          params, views().horizontal_tab_strip_region_view, leading_margin);
       params.SetTop(tabstrip_bounds.bottom() -
                     GetLayoutConstant(LayoutConstant::kTabstripToolbarOverlap));
       needs_exclusion = false;
@@ -679,18 +695,20 @@
   if (IsParentedToAndVisible(views().projects_panel_container,
                              views().browser_view)) {
     int target_width = projects_panel::kProjectsPanelMinWidth;
-    bool elevated = true;
+    bool projects_panel_should_appear_elevated = true;
     if (tab_strip_type == TabStripType::kVertical) {
-      elevated = horizontal_layout.vertical_tab_strip_width <
-                 projects_panel::kProjectsPanelMinWidth;
-      if (!elevated) {
+      projects_panel_should_appear_elevated =
+          horizontal_layout.vertical_tab_strip_width <
+          projects_panel::kProjectsPanelMinWidth;
+      if (!projects_panel_should_appear_elevated) {
         target_width = std::max(target_width - views::Separator::kThickness,
                                 horizontal_layout.vertical_tab_strip_width -
                                     views::Separator::kThickness);
       }
     }
     views().projects_panel_container->SetTargetWidth(target_width);
-    views().projects_panel_container->SetIsElevated(elevated);
+    views().projects_panel_container->SetIsElevated(
+        projects_panel_should_appear_elevated);
 
     const double reveal_amount =
         views().projects_panel_container->GetResizeAnimationValue();
@@ -1064,20 +1082,13 @@
     params.Inset(gfx::Insets::TLBR(height, 0, 0, 0));
   }
 
-  // If the tabstrip is in the top container (which can happen in immersive
-  // mode), ensure it is laid out here.
   if (IsParentedTo(views().horizontal_tab_strip_region_view,
                    views().top_container)) {
     gfx::Rect tabstrip_bounds;
     if (tab_strip_type == TabStripType::kHorizontal) {
-      // When there is an exclusion, inset the leading edge of the tabstrip by
-      // the size of the swoop of the first tab; this is especially important
-      // for Mac, where the negative space of the caption button margins and the
-      // edge of the tabstrip should overlap. The trailing edge receives the
-      // usual treatment, as it is the new tab button and not a tab.
+      const int leading_margin = GetHorizontalTabStripLeadingMargin(params);
       tabstrip_bounds = GetBoundsWithExclusion(
-          params, views().horizontal_tab_strip_region_view,
-          TabStyle::Get()->GetBottomCornerRadius());
+          params, views().horizontal_tab_strip_region_view, leading_margin);
       params.SetTop(tabstrip_bounds.bottom() -
                     GetLayoutConstant(LayoutConstant::kTabstripToolbarOverlap));
       needs_exclusion = false;
@@ -1226,6 +1237,30 @@
     }
     vertical_tabs_background->SetCorners(vertical_tabs_corners);
 
+    // When the projects panel is animating open or closed and does not appear
+    // elevated, the background of vertical tabs should fade to match the
+    // background color of the panel.
+    if (tab_groups::IsProjectsPanelFeatureEnabled()) {
+      CustomFloatingCorner* const vertical_tabs_top_corner =
+          views().vertical_tab_strip_top_corner;
+      CustomFloatingCorner* const vertical_tabs_bottom_corner =
+          views().vertical_tab_strip_bottom_corner;
+      if (!views().projects_panel_container->is_elevated()) {
+        auto projects_panel_reveal_amount =
+            views().projects_panel_container->GetResizeAnimationValue();
+        CustomCorners::FadeBackground const fade_background{
+            .color = projects_panel::kProjectsPanelBackgroundColor,
+            .opacity = static_cast<float>(projects_panel_reveal_amount)};
+        vertical_tabs_background->SetFadeBackground(fade_background);
+        vertical_tabs_top_corner->SetFadeBackground(fade_background);
+        vertical_tabs_bottom_corner->SetFadeBackground(fade_background);
+      } else {
+        vertical_tabs_background->SetFadeBackground(std::nullopt);
+        vertical_tabs_top_corner->SetFadeBackground(std::nullopt);
+        vertical_tabs_bottom_corner->SetFadeBackground(std::nullopt);
+      }
+    }
+
     // Vertical tabs outline always draws trailing edge.
     CustomCornersBackground::Outline vertical_tabs_outline;
     vertical_tabs_outline.color = kColorVerticalTabStripShadow;
diff --git a/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.h b/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.h
index ca2fb9a9..000267d 100644
--- a/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.h
+++ b/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.h
@@ -133,6 +133,10 @@
     kMultiContents
   };
   TopSeparatorType GetTopSeparatorType() const;
+
+  // Returns the leading margin for the horizontal tab strip region.
+  int GetHorizontalTabStripLeadingMargin(
+      const BrowserLayoutParams& params) const;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_FRAME_LAYOUT_BROWSER_VIEW_TABBED_LAYOUT_IMPL_H_
diff --git a/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.cc b/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.cc
index 1b05c0a5..aa6d81d 100644
--- a/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.cc
+++ b/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.cc
@@ -62,6 +62,8 @@
 
 namespace {
 constexpr int kRegionVerticalPadding = 5;
+constexpr int kResizeAreaWidth = 5;
+constexpr int kCollapsedResizeAreaWidth = 2;
 }  // namespace
 
 VerticalTabStripRegionView::VerticalTabStripRegionView(
@@ -69,6 +71,7 @@
     actions::ActionItem* root_action_item,
     BrowserView* browser_view)
     : browser_view_(browser_view),
+      resize_area_width_(kResizeAreaWidth),
       tab_strip_model_(browser_view->browser()->GetTabStripModel()),
       state_controller_(state_controller),
       root_action_item_(root_action_item),
@@ -172,8 +175,9 @@
 
   // Manually position the resize area as it overlaps views handled by the flex
   // layout.
-  resize_area_->SetBoundsRect(gfx::Rect(bounds().right() - kResizeAreaWidth, 0,
-                                        kResizeAreaWidth, bounds().height()));
+  resize_area_->SetBoundsRect(gfx::Rect(bounds().right() - resize_area_width_,
+                                        0, resize_area_width_,
+                                        bounds().height()));
 }
 
 views::View* VerticalTabStripRegionView::GetDefaultFocusableChild() {
@@ -618,6 +622,10 @@
           GetLayoutConstant(LayoutConstant::kVerticalTabStripCollapsedPadding),
           padding, 0, padding));
 
+  resize_area_width_ = state_controller->IsCollapsed()
+                           ? kCollapsedResizeAreaWidth
+                           : kResizeAreaWidth;
+
   flex_layout_->SetInteriorMargin(gfx::Insets::TLBR(
       0, 0,
       GetLayoutConstant(LayoutConstant::kVerticalTabStripUncollapsedPadding),
diff --git a/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.h b/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.h
index 1e76289..deff36f 100644
--- a/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.h
+++ b/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.h
@@ -48,7 +48,6 @@
   METADATA_HEADER(VerticalTabStripRegionView, TabStripRegionView)
 
  public:
-  static constexpr int kResizeAreaWidth = 6;
   // TODO(crbug.com/465833741): Replace constant with derived value based on
   // caption buttons.
   static constexpr int kUncollapsedMinWidth = 126;
@@ -183,6 +182,7 @@
   raw_ptr<VerticalTabStripBottomContainer> bottom_button_container_ = nullptr;
   raw_ptr<views::View> gemini_button_ = nullptr;
   raw_ptr<views::ResizeArea> resize_area_ = nullptr;
+  int resize_area_width_;
   raw_ptr<views::FlexLayout> flex_layout_ = nullptr;
 
   // The drag handler is a view (required for capturing mouse inputs during
diff --git a/chrome/browser/ui/views/frame/vertical_tab_strip_region_view_browsertest.cc b/chrome/browser/ui/views/frame/vertical_tab_strip_region_view_browsertest.cc
index 7c7d11e..777bac6 100644
--- a/chrome/browser/ui/views/frame/vertical_tab_strip_region_view_browsertest.cc
+++ b/chrome/browser/ui/views/frame/vertical_tab_strip_region_view_browsertest.cc
@@ -125,9 +125,6 @@
   EXPECT_EQ(region_view()->bounds().height(),
             region_view()->resize_area_for_testing()->bounds().height());
   EXPECT_EQ(0, region_view()->resize_area_for_testing()->bounds().y());
-  // Verify resize area width.
-  EXPECT_EQ(VerticalTabStripRegionView::kResizeAreaWidth,
-            region_view()->resize_area_for_testing()->bounds().width());
 }
 
 IN_PROC_BROWSER_TEST_F(VerticalTabStripRegionViewTest, ResizeViewSmaller) {
diff --git a/chrome/browser/ui/views/location_bar/omnibox_popup_file_selector.cc b/chrome/browser/ui/views/location_bar/omnibox_popup_file_selector.cc
index 11cd996..171ccd2 100644
--- a/chrome/browser/ui/views/location_bar/omnibox_popup_file_selector.cc
+++ b/chrome/browser/ui/views/location_bar/omnibox_popup_file_selector.cc
@@ -105,6 +105,10 @@
 
 void OmniboxPopupFileSelector::OnFileDataReady(
     std::unique_ptr<FileData> file_data) {
+  base::UmaHistogramExactLinear(
+      "ContextualSearch.ContextAdded.ContextAddedMethod.Omnibox",
+      /*ContextMenu*/ 0, 4);
+
   lens::MimeType mime_type;
   if (file_data->mime_type.find("pdf") != std::string::npos) {
     mime_type = lens::MimeType::kPdf;
diff --git a/chrome/browser/ui/views/location_bar/omnibox_popup_file_selector_browsertest.cc b/chrome/browser/ui/views/location_bar/omnibox_popup_file_selector_browsertest.cc
index 0b85fa1..2d4961a 100644
--- a/chrome/browser/ui/views/location_bar/omnibox_popup_file_selector_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/omnibox_popup_file_selector_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/callback_helpers.h"
 #include "base/run_loop.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/browser_window/public/browser_window_features.h"
@@ -121,3 +122,41 @@
   EXPECT_EQ(file_attachment->name, "test.txt");
   EXPECT_EQ(file_attachment->mime_type, "text/plain");
 }
+
+IN_PROC_BROWSER_TEST_F(OmniboxPopupFileSelectorBrowserTest,
+                       RecordHistogramOnFileSelected) {
+  base::HistogramTester histogram_tester;
+
+  auto* omnibox_controller =
+      browser()->window()->GetLocationBar()->GetOmniboxController();
+  MockOmniboxEditModel mock_edit_model(omnibox_controller);
+
+  OmniboxPopupFileSelector file_selector(
+      browser()->window()->GetNativeWindow());
+
+  auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
+  file_selector.OpenFileUploadDialog(web_contents,
+                                     /*is_image=*/false, &mock_edit_model,
+                                     std::nullopt,
+                                     /*was_ai_mode_open=*/true);
+
+  // Create a real temporary file.
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath text_file_path = temp_dir.GetPath().AppendASCII("test.txt");
+  ASSERT_TRUE(base::WriteFile(text_file_path, "dummy data"));
+
+  base::RunLoop run_loop;
+  EXPECT_CALL(mock_edit_model, OpenAiMode(false, true))
+      .WillOnce(testing::InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
+
+  // Trigger the file selection.
+  file_selector.FileSelected(
+      ui::SelectedFileInfo(text_file_path, text_file_path), 0);
+
+  run_loop.Run();
+
+  histogram_tester.ExpectUniqueSample(
+      "ContextualSearch.ContextAdded.ContextAddedMethod.Omnibox", 0, 1);
+}
diff --git a/chrome/browser/ui/views/page_action/page_action_model.cc b/chrome/browser/ui/views/page_action/page_action_model.cc
index 55c93a37..68b9b18 100644
--- a/chrome/browser/ui/views/page_action/page_action_model.cc
+++ b/chrome/browser/ui/views/page_action/page_action_model.cc
@@ -29,7 +29,7 @@
     return;
   }
   show_requested_ = requested;
-  NotifyChange();
+  NotifyChange(Property::kShowRequested);
 }
 
 void PageActionModel::SetShouldShowSuggestionChip(
@@ -40,7 +40,7 @@
     return;
   }
   should_show_suggestion_chip_ = show;
-  NotifyChange();
+  NotifyChange(Property::kShouldShowSuggestionChip);
 }
 
 void PageActionModel::SetSuggestionChipConfig(
@@ -52,7 +52,7 @@
   }
   should_animate_ = config.should_animate;
   should_announce_chip_ = config.should_announce_chip;
-  NotifyChange();
+  NotifyChange(Property::kSuggestionChipConfig);
 }
 
 void PageActionModel::SetTabActive(base::PassKey<PageActionController>,
@@ -61,7 +61,7 @@
     return;
   }
   is_tab_active_ = is_active;
-  NotifyChange();
+  NotifyChange(Property::kTabActive);
 }
 
 void PageActionModel::SetHasPinnedIcon(base::PassKey<PageActionController>,
@@ -70,7 +70,7 @@
     return;
   }
   has_pinned_icon_ = has_pinned_icon;
-  NotifyChange();
+  NotifyChange(Property::kHasPinnedIcon);
 }
 
 void PageActionModel::SetActionItemProperties(
@@ -104,7 +104,7 @@
   }
 
   if (model_changed) {
-    NotifyChange();
+    NotifyChange(Property::kActionItemProperties);
   }
 }
 
@@ -176,7 +176,7 @@
     return;
   }
   override_text_ = override_text;
-  NotifyChange();
+  NotifyChange(Property::kOverrideText);
 }
 
 void PageActionModel::SetOverrideAccessibleName(
@@ -186,7 +186,7 @@
     return;
   }
   override_accessible_name_ = override_accessible_name;
-  NotifyChange();
+  NotifyChange(Property::kOverrideAccessibleName);
 }
 
 void PageActionModel::SetOverrideImage(
@@ -198,7 +198,7 @@
   }
   override_image_ = override_image;
   color_source_ = color_source;
-  NotifyChange();
+  NotifyChange(Property::kOverrideImage);
 }
 
 void PageActionModel::SetOverrideTooltip(
@@ -208,7 +208,7 @@
     return;
   }
   override_tooltip_ = override_tooltip;
-  NotifyChange();
+  NotifyChange(Property::kOverrideTooltip);
 }
 
 void PageActionModel::SetIsSuppressedByOmnibox(
@@ -218,7 +218,7 @@
     return;
   }
   is_suppressed_by_omnibox_ = is_suppressed;
-  NotifyChange();
+  NotifyChange(Property::kIsSuppressedByOmnibox);
 }
 
 void PageActionModel::SetExemptFromOmniboxSuppression(
@@ -228,7 +228,7 @@
     return;
   }
   is_exempt_from_omnibox_suppression_ = is_exempt;
-  NotifyChange();
+  NotifyChange(Property::kExemptFromOmniboxSuppression);
 }
 
 void PageActionModel::SetIsChipShowing(base::PassKey<PageActionController>,
@@ -239,7 +239,7 @@
   }
 
   is_chip_showing_ = is_chip_showing;
-  NotifyChange();
+  NotifyChange(Property::kIsChipShowing);
 }
 
 void PageActionModel::SetActionActive(base::PassKey<PageActionController>,
@@ -249,7 +249,7 @@
   }
 
   action_active_ = is_active;
-  NotifyChange();
+  NotifyChange(Property::kActionActive);
 }
 
 void PageActionModel::AddObserver(PageActionModelObserver* observer) {
@@ -260,12 +260,23 @@
   observer_list_.RemoveObserver(observer);
 }
 
-void PageActionModel::NotifyChange() {
-  CHECK(!is_notifying_observers_)
-      << "PageActionModel should not be updated while notifying observers";
+void PageActionModel::NotifyChange(Property property) {
+  // Crash if the same property is modified again during notification, as this
+  // would cause an infinite loop (A notifies -> observer sets A -> notifies
+  // -> ...).
+  CHECK(!notified_properties_.Has(property));
+  notified_properties_.Put(property);
+
+  if (is_notifying_observers_) {
+    notified_properties_.Remove(property);
+    return;
+  }
+
   base::AutoReset<bool> auto_reset(&is_notifying_observers_, true);
   observer_list_.Notify(&PageActionModelObserver::OnPageActionModelChanged,
                         *this);
+
+  notified_properties_.Remove(property);
 }
 
 bool PageActionModel::IsEphemeral() const {
@@ -279,7 +290,7 @@
     return;
   }
   should_show_anchored_message_ = show;
-  NotifyChange();
+  NotifyChange(Property::kShouldShowAnchoredMessage);
 }
 
 void PageActionModel::SetAnchoredMessageText(
@@ -289,7 +300,7 @@
     return;
   }
   anchored_message_text_ = anchored_message;
-  NotifyChange();
+  NotifyChange(Property::kAnchoredMessageText);
 }
 
 void PageActionModel::SetAnchoredMessageCloseIcon(
@@ -299,7 +310,7 @@
     return;
   }
   anchored_message_show_close_icon_ = anchored_message_show_close_icon;
-  NotifyChange();
+  NotifyChange(Property::kAnchoredMessageCloseIcon);
 }
 
 bool PageActionModel::ShouldShowAnchoredMessage() const {
@@ -317,7 +328,7 @@
     return;
   }
   is_anchored_message_showing_ = is_anchored_message_showing;
-  NotifyChange();
+  NotifyChange(Property::kIsAnchoredMessageShowing);
 }
 
 const std::u16string& PageActionModel::GetAnchoredMessageText() const {
diff --git a/chrome/browser/ui/views/page_action/page_action_model.h b/chrome/browser/ui/views/page_action/page_action_model.h
index ad8740a..c8ba568 100644
--- a/chrome/browser/ui/views/page_action/page_action_model.h
+++ b/chrome/browser/ui/views/page_action/page_action_model.h
@@ -10,6 +10,7 @@
 #include <optional>
 #include <string>
 
+#include "base/containers/enum_set.h"
 #include "base/functional/callback_forward.h"
 #include "base/observer_list.h"
 #include "base/types/pass_key.h"
@@ -195,8 +196,37 @@
   bool IsEphemeral() const override;
 
  private:
-  // Notifies observers of a model change.
-  void NotifyChange();
+  // Identifies which property triggered a NotifyChange call, used for
+  // per-property reentrancy checks.
+  enum class Property {
+    kShowRequested,
+    kShouldShowSuggestionChip,
+    kSuggestionChipConfig,
+    kTabActive,
+    kHasPinnedIcon,
+    kActionItemProperties,
+    kOverrideText,
+    kOverrideAccessibleName,
+    kOverrideImage,
+    kOverrideTooltip,
+    kIsSuppressedByOmnibox,
+    kExemptFromOmniboxSuppression,
+    kIsChipShowing,
+    kActionActive,
+    kShouldShowAnchoredMessage,
+    kAnchoredMessageText,
+    kAnchoredMessageCloseIcon,
+    kIsAnchoredMessageShowing,
+    kMaxValue = kIsAnchoredMessageShowing,
+  };
+  using PropertySet =
+      base::EnumSet<Property, Property::kShowRequested, Property::kMaxValue>;
+
+  // Notifies observers of a model change. `property` identifies the property
+  // that was modified, used for reentrancy checks. Re-entrant modifications to
+  // the same property CHECK-fail, as they would cause an infinite notification
+  // loop.
+  void NotifyChange(Property property);
 
   // Represents whether this page action will be always visible or not.
   const bool is_ephemeral_ = false;
@@ -271,9 +301,14 @@
   // by `is_suppressed_by_omnibox_` variable (eg. AI mode page action).
   bool is_exempt_from_omnibox_suppression_ = false;
 
-  // Flag used to disallow reentrant behaviour.
+  // Flag used while notifying observers.
   bool is_notifying_observers_ = false;
 
+  // Tracks which properties have been modified during the current notification
+  // cycle. Used to detect infinite loops: if the same property is modified
+  // again during notification, we CHECK-fail.
+  PropertySet notified_properties_;
+
   base::ObserverList<PageActionModelObserver> observer_list_;
 };
 
diff --git a/chrome/browser/ui/views/page_action/page_action_model_unittest.cc b/chrome/browser/ui/views/page_action/page_action_model_unittest.cc
index 73324b4..e27885e3 100644
--- a/chrome/browser/ui/views/page_action/page_action_model_unittest.cc
+++ b/chrome/browser/ui/views/page_action/page_action_model_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/views/page_action/page_action_model.h"
 
+#include "base/memory/raw_ref.h"
 #include "base/types/pass_key.h"
 #include "chrome/browser/ui/views/page_action/page_action_controller.h"
 #include "chrome/browser/ui/views/page_action/page_action_model_observer.h"
@@ -42,6 +43,31 @@
               (override));
 };
 
+class ReentrantPageActionModelObserver : public PageActionModelObserver {
+ public:
+  explicit ReentrantPageActionModelObserver(PageActionModel& model)
+      : model_(model) {}
+
+  void OnPageActionModelChanged(
+      const PageActionModelInterface& model) override {
+    ++change_count_;
+    if (!did_trigger_reentrant_update_) {
+      did_trigger_reentrant_update_ = true;
+      model_->SetActionActive(PassKey(), true);
+    }
+  }
+
+  void OnPageActionModelWillBeDeleted(
+      const PageActionModelInterface& model) override {}
+
+  int change_count() const { return change_count_; }
+
+ private:
+  const raw_ref<PageActionModel> model_;
+  int change_count_ = 0;
+  bool did_trigger_reentrant_update_ = false;
+};
+
 class PageActionModelTest : public ::testing::Test {
  protected:
   void SetUp() override { model_.AddObserver(&observer_); }
@@ -282,6 +308,19 @@
   testing::Mock::VerifyAndClearExpectations(&observer_);
 }
 
+TEST(PageActionModelReentrancyTest, AppliesReentrantUpdateWithoutSecondNotify) {
+  PageActionModel model;
+  ReentrantPageActionModelObserver observer(model);
+  model.AddObserver(&observer);
+
+  model.SetShowRequested(PassKey(), true);
+
+  EXPECT_TRUE(model.GetActionActive());
+  EXPECT_EQ(observer.change_count(), 1);
+
+  model.RemoveObserver(&observer);
+}
+
 TEST_F(PageActionModelTest, OverrideImageWithColorSource) {
   model_.SetActionItemProperties(
       PassKey(), ActionItem::Builder().SetImage(kTestImage).Build().get());
diff --git a/chrome/browser/ui/views/tabs/projects/BUILD.gn b/chrome/browser/ui/views/tabs/projects/BUILD.gn
index 280b166..1f0568f9 100644
--- a/chrome/browser/ui/views/tabs/projects/BUILD.gn
+++ b/chrome/browser/ui/views/tabs/projects/BUILD.gn
@@ -20,6 +20,7 @@
     "//base",
     "//chrome/app/vector_icons",
     "//chrome/browser/ui/tabs/projects",
+    "//components/contextual_tasks/public",
     "//components/saved_tab_groups/public",
     "//ui/base",
     "//ui/views",
@@ -44,6 +45,7 @@
   deps = [
     "//chrome/app:generated_resources",
     "//chrome/app/vector_icons",
+    "//chrome/browser/contextual_tasks",
     "//chrome/browser/tab_group_sync:factories",
     "//chrome/browser/ui",
     "//chrome/browser/ui:browser_element_identifiers",
@@ -78,10 +80,12 @@
     "//base/test:test_support",
     "//build:branding_buildflags",
     "//chrome/app/vector_icons",
+    "//chrome/browser/contextual_tasks",
     "//chrome/browser/tab_group_sync:factories",
     "//chrome/browser/ui:test_support",
     "//chrome/test:test_support",
     "//components/contextual_tasks/public",
+    "//components/contextual_tasks/public:test_support",
     "//components/saved_tab_groups/public",
     "//components/saved_tab_groups/test_support",
     "//components/sync/base",
diff --git a/chrome/browser/ui/views/tabs/projects/layout_constants.h b/chrome/browser/ui/views/tabs/projects/layout_constants.h
index 835352a..dda12ff 100644
--- a/chrome/browser/ui/views/tabs/projects/layout_constants.h
+++ b/chrome/browser/ui/views/tabs/projects/layout_constants.h
@@ -34,6 +34,10 @@
 // Minimum width of the projects panel.
 inline constexpr int kProjectsPanelMinWidth = 240;
 
+// Background color of the projects panel.
+inline constexpr ui::ColorId kProjectsPanelBackgroundColor =
+    ui::kColorSysSurface2;
+
 }  // namespace projects_panel
 
 #endif  // CHROME_BROWSER_UI_VIEWS_TABS_PROJECTS_LAYOUT_CONSTANTS_H_
diff --git a/chrome/browser/ui/views/tabs/projects/projects_panel_controller.cc b/chrome/browser/ui/views/tabs/projects/projects_panel_controller.cc
index 52e88578..494a09e 100644
--- a/chrome/browser/ui/views/tabs/projects/projects_panel_controller.cc
+++ b/chrome/browser/ui/views/tabs/projects/projects_panel_controller.cc
@@ -11,9 +11,15 @@
 #include "components/saved_tab_groups/public/saved_tab_group.h"
 
 ProjectsPanelController::ProjectsPanelController(
-    tab_groups::TabGroupSyncService* tab_group_sync_service)
-    : tab_group_sync_service_(tab_group_sync_service) {
+    tab_groups::TabGroupSyncService* tab_group_sync_service,
+    contextual_tasks::ContextualTasksService* contextual_tasks_service)
+    : tab_group_sync_service_(tab_group_sync_service),
+      contextual_tasks_service_(contextual_tasks_service) {
   tab_group_sync_service_observer_.Observe(tab_group_sync_service);
+
+  if (contextual_tasks_service) {
+    contextual_tasks_service_observer_.Observe(contextual_tasks_service);
+  }
 }
 
 ProjectsPanelController::~ProjectsPanelController() = default;
@@ -45,6 +51,11 @@
   observers_.RemoveObserver(observer);
 }
 
+const std::vector<contextual_tasks::Thread>&
+ProjectsPanelController::GetThreads() {
+  return threads_;
+}
+
 void ProjectsPanelController::OnInitialized() {
   tab_groups_ = tab_group_sync_service_->GetAllGroups();
 
@@ -123,3 +134,24 @@
     observer.OnTabGroupsReordered(tab_groups_);
   }
 }
+
+void ProjectsPanelController::OnContextualTasksServiceInitialized() {
+  contextual_tasks_service_->GetTasks(base::BindOnce(
+      [](base::WeakPtr<ProjectsPanelController> weak_this,
+         std::vector<contextual_tasks::ContextualTask> tasks) {
+        if (!weak_this) {
+          return;
+        }
+        weak_this->threads_ = std::vector<contextual_tasks::Thread>();
+        for (auto& task : tasks) {
+          if (task.GetThread().has_value()) {
+            weak_this->threads_.push_back(task.GetThread().value());
+          }
+        }
+
+        for (auto& observer : weak_this->observers_) {
+          observer.OnThreadsInitialized(weak_this->threads_);
+        }
+      },
+      weak_ptr_factory_.GetWeakPtr()));
+}
diff --git a/chrome/browser/ui/views/tabs/projects/projects_panel_controller.h b/chrome/browser/ui/views/tabs/projects/projects_panel_controller.h
index e941a23..7b733389 100644
--- a/chrome/browser/ui/views/tabs/projects/projects_panel_controller.h
+++ b/chrome/browser/ui/views/tabs/projects/projects_panel_controller.h
@@ -9,8 +9,11 @@
 #include <vector>
 
 #include "base/memory/raw_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/scoped_observation.h"
+#include "components/contextual_tasks/public/contextual_task.h"
+#include "components/contextual_tasks/public/contextual_tasks_service.h"
 #include "components/saved_tab_groups/public/tab_group_sync_service.h"
 
 namespace tab_groups {
@@ -21,7 +24,9 @@
 
 // Controller for the projects panel view. Handles fetching, resuming, and
 // activating tab groups and recent chat threads.
-class ProjectsPanelController : tab_groups::TabGroupSyncService::Observer {
+class ProjectsPanelController
+    : tab_groups::TabGroupSyncService::Observer,
+      contextual_tasks::ContextualTasksService::Observer {
  public:
   class Observer : public base::CheckedObserver {
    public:
@@ -34,10 +39,13 @@
                                    int old_index) = 0;
     virtual void OnTabGroupsReordered(
         const std::vector<tab_groups::SavedTabGroup>& tab_groups) = 0;
+    virtual void OnThreadsInitialized(
+        const std::vector<contextual_tasks::Thread>& threads) = 0;
   };
 
-  explicit ProjectsPanelController(
-      tab_groups::TabGroupSyncService* tab_group_sync_service);
+  ProjectsPanelController(
+      tab_groups::TabGroupSyncService* tab_group_sync_service,
+      contextual_tasks::ContextualTasksService* contextual_tasks_service);
   ProjectsPanelController(const ProjectsPanelController&) = delete;
   ProjectsPanelController& operator=(const ProjectsPanelController&) = delete;
   ~ProjectsPanelController() override;
@@ -56,6 +64,8 @@
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
 
+  const std::vector<contextual_tasks::Thread>& GetThreads();
+
   // tab_groups::TabGroupSyncService::Observer:
   void OnInitialized() override;
   void OnTabGroupAdded(const tab_groups::SavedTabGroup& group,
@@ -69,16 +79,26 @@
       const std::optional<tab_groups::LocalTabGroupID>& local_id) override;
   void OnTabGroupsReordered(tab_groups::TriggerSource source) override;
 
+  // ContextualTasksService::Observer
+  void OnContextualTasksServiceInitialized() override;
+
  private:
   void SortTabGroups();
 
   const raw_ptr<tab_groups::TabGroupSyncService> tab_group_sync_service_;
+  const raw_ptr<contextual_tasks::ContextualTasksService>
+      contextual_tasks_service_;
   std::vector<tab_groups::SavedTabGroup> tab_groups_;
+  std::vector<contextual_tasks::Thread> threads_;
 
   base::ObserverList<Observer> observers_;
   base::ScopedObservation<tab_groups::TabGroupSyncService,
                           tab_groups::TabGroupSyncService::Observer>
       tab_group_sync_service_observer_{this};
+  base::ScopedObservation<contextual_tasks::ContextualTasksService,
+                          contextual_tasks::ContextualTasksService::Observer>
+      contextual_tasks_service_observer_{this};
+  base::WeakPtrFactory<ProjectsPanelController> weak_ptr_factory_{this};
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_TABS_PROJECTS_PROJECTS_PANEL_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/tabs/projects/projects_panel_controller_unittest.cc b/chrome/browser/ui/views/tabs/projects/projects_panel_controller_unittest.cc
index 6693f68e..bc29ff2 100644
--- a/chrome/browser/ui/views/tabs/projects/projects_panel_controller_unittest.cc
+++ b/chrome/browser/ui/views/tabs/projects/projects_panel_controller_unittest.cc
@@ -10,6 +10,8 @@
 #include "base/time/time.h"
 #include "base/uuid.h"
 #include "chrome/browser/ui/browser_window/test/mock_browser_window_interface.h"
+#include "components/contextual_tasks/public/contextual_task.h"
+#include "components/contextual_tasks/public/mock_contextual_tasks_service.h"
 #include "components/saved_tab_groups/public/saved_tab_group.h"
 #include "components/saved_tab_groups/test_support/mock_tab_group_sync_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -88,6 +90,10 @@
               OnTabGroupsReordered,
               (const std::vector<tab_groups::SavedTabGroup>& tab_groups),
               (override));
+  MOCK_METHOD(void,
+              OnThreadsInitialized,
+              (const std::vector<contextual_tasks::Thread>& threads),
+              (override));
 };
 
 MATCHER_P(GroupIs, expected_group, "") {
@@ -100,12 +106,14 @@
  protected:
   std::unique_ptr<ProjectsPanelController> GetInitializedController() {
     auto controller = std::make_unique<ProjectsPanelController>(
-        &mock_tab_group_sync_service_);
+        &mock_tab_group_sync_service_, &mock_contextual_tasks_service_);
     controller->OnInitialized();
     return controller;
   }
   testing::NiceMock<tab_groups::MockTabGroupSyncService>
       mock_tab_group_sync_service_;
+  testing::NiceMock<contextual_tasks::MockContextualTasksService>
+      mock_contextual_tasks_service_;
 };
 
 TEST_F(ProjectsPanelControllerTest, PreservesOrderOnConstruction) {
@@ -206,7 +214,7 @@
  public:
   void SetUp() override {
     controller_ = std::make_unique<ProjectsPanelController>(
-        &mock_tab_group_sync_service_);
+        &mock_tab_group_sync_service_, &mock_contextual_tasks_service_);
     controller_->AddObserver(&observer_);
   }
 
diff --git a/chrome/browser/ui/views/tabs/projects/projects_panel_view.cc b/chrome/browser/ui/views/tabs/projects/projects_panel_view.cc
index acfca4b5..318235cd 100644
--- a/chrome/browser/ui/views/tabs/projects/projects_panel_view.cc
+++ b/chrome/browser/ui/views/tabs/projects/projects_panel_view.cc
@@ -4,10 +4,12 @@
 
 #include "chrome/browser/ui/views/tabs/projects/projects_panel_view.h"
 
+#include <algorithm>
 #include <memory>
 #include <utility>
 
 #include "base/task/single_thread_task_runner.h"
+#include "chrome/browser/contextual_tasks/contextual_tasks_service_factory.h"
 #include "chrome/browser/tab_group_sync/tab_group_sync_service_factory.h"
 #include "chrome/browser/ui/actions/chrome_action_id.h"
 #include "chrome/browser/ui/browser.h"
@@ -48,7 +50,6 @@
 
 namespace {
 constexpr int kClipRectRightMarginForShadow = 32;
-constexpr ui::ColorId kProjectPanelBackgroundColor = ui::kColorSysSurface2;
 constexpr int kProjectPanelRightCornerRadius = 16;
 constexpr gfx::Insets kRegionInteriorMargins = gfx::Insets::VH(12, 12);
 constexpr int kShadowElevation = 2;
@@ -68,7 +69,7 @@
 }
 
 void SetScrollViewProperties(views::ScrollView& scroll_view) {
-  scroll_view.SetBackgroundColor(kProjectPanelBackgroundColor);
+  scroll_view.SetBackgroundColor(projects_panel::kProjectsPanelBackgroundColor);
   scroll_view.SetHorizontalScrollBarMode(
       views::ScrollView::ScrollBarMode::kDisabled);
   scroll_view.SetVerticalScrollBarMode(
@@ -132,7 +133,11 @@
 
   panel_controller_ = std::make_unique<ProjectsPanelController>(
       tab_groups::TabGroupSyncServiceFactory::GetForProfile(
-          browser->GetProfile()));
+          browser->GetProfile()),
+      tab_groups::IsThreadsInProjectsPanelEnabled()
+          ? contextual_tasks::ContextualTasksServiceFactory::GetForProfile(
+                browser->GetProfile())
+          : nullptr);
   panel_controller_observer_.Observe(panel_controller_.get());
 
   controls_view_ = content_container_->AddChildView(
@@ -174,10 +179,9 @@
     views::ScrollView* threads_scroll_view =
         content_container_->AddChildView(std::make_unique<views::ScrollView>(
             views::ScrollView::ScrollWithLayers::kEnabled));
-    // TODO(crbug.com/475300882): Fetch thread data from the controller once
-    // available.
-    threads_scroll_view->SetContents(
-        std::make_unique<ProjectsPanelRecentThreadsView>(threads_));
+    auto threads_view = std::make_unique<ProjectsPanelRecentThreadsView>(
+        panel_controller_->GetThreads());
+    threads_view_ = threads_scroll_view->SetContents(std::move(threads_view));
     SetScrollViewProperties(*threads_scroll_view);
   }
 
@@ -219,6 +223,9 @@
     // TODO(crbug.com/477602874): Have the panel view observe the controller and
     // pipe updates to the list.
     tab_groups_view_->SetTabGroups(panel_controller_->GetTabGroups());
+    if (threads_view_) {
+      threads_view_->SetThreads(panel_controller_->GetThreads());
+    }
   } else {
     event_monitor_.reset();
   }
@@ -271,7 +278,7 @@
   content_container_->layer()->SetRoundedCornerRadius(
       gfx::RoundedCornersF(0, corner_radius, corner_radius, 0));
   content_container_->SetBackground(views::CreateRoundedRectBackground(
-      kProjectPanelBackgroundColor,
+      projects_panel::kProjectsPanelBackgroundColor,
       gfx::RoundedCornersF(0, corner_radius, corner_radius, 0)));
 
   InvalidateLayout();
@@ -336,6 +343,13 @@
   tab_groups_view_->SetTabGroups(tab_groups);
 }
 
+void ProjectsPanelView::OnThreadsInitialized(
+    const std::vector<contextual_tasks::Thread>& threads) {
+  if (threads_view_) {
+    threads_view_->SetThreads(threads);
+  }
+}
+
 // static
 void ProjectsPanelView::disable_animations_for_testing() {
   disable_animations_for_testing_ = true;
diff --git a/chrome/browser/ui/views/tabs/projects/projects_panel_view.h b/chrome/browser/ui/views/tabs/projects/projects_panel_view.h
index 4b6e931..73f3449 100644
--- a/chrome/browser/ui/views/tabs/projects/projects_panel_view.h
+++ b/chrome/browser/ui/views/tabs/projects/projects_panel_view.h
@@ -18,10 +18,6 @@
 #include "ui/views/controls/separator.h"
 #include "ui/views/view.h"
 
-namespace contextual_tasks {
-struct Thread;
-}  // namespace contextual_tasks
-
 namespace gfx {
 class Point;
 }  // namespace gfx
@@ -38,7 +34,9 @@
 }  // namespace views
 
 class BrowserWindowInterface;
+
 class ProjectsPanelController;
+class ProjectsPanelRecentThreadsView;
 class ProjectsPanelStateController;
 class ProjectsPanelTabGroupsView;
 
@@ -71,6 +69,9 @@
   // Set whether the panel should appear elevated with rounded borders.
   void SetIsElevated(bool elevated);
 
+  // Whether the panel appears elevated with rounded borders.
+  bool is_elevated() { return elevated_; }
+
   // views::View:
   void Layout(PassKey) override;
   bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
@@ -88,6 +89,8 @@
   void OnTabGroupRemoved(const base::Uuid& sync_id, int old_index) override;
   void OnTabGroupsReordered(
       const std::vector<tab_groups::SavedTabGroup>& tab_groups) override;
+  void OnThreadsInitialized(
+      const std::vector<contextual_tasks::Thread>& threads) override;
 
   views::View* content_container_for_testing() { return content_container_; }
 
@@ -127,13 +130,10 @@
   raw_ptr<views::View> content_container_ = nullptr;
   raw_ptr<ProjectsPanelControlsView> controls_view_ = nullptr;
   raw_ptr<ProjectsPanelTabGroupsView> tab_groups_view_ = nullptr;
+  raw_ptr<ProjectsPanelRecentThreadsView> threads_view_ = nullptr;
 
   std::unique_ptr<views::ViewShadow> content_shadow_;
 
-  // TODO(crbug.com/475300882): Remove once we fetch thread data from the
-  // controller.
-  const std::vector<contextual_tasks::Thread> threads_;
-
   std::unique_ptr<views::ActionViewController> action_view_controller_;
   std::unique_ptr<ProjectsPanelController> panel_controller_;
 
diff --git a/chrome/browser/ui/views/tabs/projects/projects_panel_view_unittest.cc b/chrome/browser/ui/views/tabs/projects/projects_panel_view_unittest.cc
index 7110fdd..77e60e82 100644
--- a/chrome/browser/ui/views/tabs/projects/projects_panel_view_unittest.cc
+++ b/chrome/browser/ui/views/tabs/projects/projects_panel_view_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/test/bind.h"
 #include "base/test/mock_callback.h"
 #include "base/test/task_environment.h"
+#include "chrome/browser/contextual_tasks/contextual_tasks_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_group_sync/tab_group_sync_service_factory.h"
 #include "chrome/browser/ui/actions/chrome_action_id.h"
@@ -18,6 +19,7 @@
 #include "chrome/browser/ui/tabs/projects/projects_panel_state_controller.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/views/chrome_views_test_base.h"
+#include "components/contextual_tasks/public/mock_contextual_tasks_service.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/saved_tab_groups/test_support/mock_tab_group_sync_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -47,6 +49,15 @@
                        &ProjectsPanelViewTest::CreateMockTabGroupSyncService,
                        base::Unretained(this)));
 
+    contextual_tasks::ContextualTasksServiceFactory::GetInstance()
+        ->SetTestingFactory(
+            profile(),
+            base::BindRepeating(
+                [](content::BrowserContext*) -> std::unique_ptr<KeyedService> {
+                  return std::make_unique<testing::NiceMock<
+                      contextual_tasks::MockContextualTasksService>>();
+                }));
+
     // Create a real State Controller.
     EXPECT_CALL(mock_browser_window_interface_, GetUnownedUserDataHost())
         .WillRepeatedly(testing::ReturnRef(unowned_user_data_host_));
diff --git a/chrome/browser/ui/views/tabs/vertical/top_container_button.cc b/chrome/browser/ui/views/tabs/vertical/top_container_button.cc
index 9b1c928..c278ccf 100644
--- a/chrome/browser/ui/views/tabs/vertical/top_container_button.cc
+++ b/chrome/browser/ui/views/tabs/vertical/top_container_button.cc
@@ -68,8 +68,8 @@
 
 ui::ColorId TopContainerButton::GetForegroundColor() const {
   return GetWidget() && GetWidget()->ShouldPaintAsActive()
-             ? kColorToolbarButtonIcon
-             : kColorToolbarButtonIconInactive;
+             ? kColorTabForegroundInactiveFrameActive
+             : kColorTabForegroundInactiveFrameInactive;
 }
 
 std::unique_ptr<views::ActionViewInterface>
diff --git a/chrome/browser/ui/views/tabs/vertical/vertical_tab_link_drop_handler.cc b/chrome/browser/ui/views/tabs/vertical/vertical_tab_link_drop_handler.cc
index 56a6c2b..b947caa 100644
--- a/chrome/browser/ui/views/tabs/vertical/vertical_tab_link_drop_handler.cc
+++ b/chrome/browser/ui/views/tabs/vertical/vertical_tab_link_drop_handler.cc
@@ -71,8 +71,19 @@
       BrowserRootView::DropIndex::GroupInclusion::kDontIncludeInGroup;
 
   if (auto group_id = tab->GetGroup()) {
-    group_inclusion =
-        BrowserRootView::DropIndex::GroupInclusion::kIncludeInGroup;
+    const TabGroup* group =
+        tab_strip_model_->group_model()->GetTabGroup(*group_id);
+    if (position_hint == DragPositionHint::kBottom &&
+        tab == group->GetLastTab()) {
+      // If dropping after the last tab in the group, then don't include the
+      // new tab in the group. Otherwise, there is ambiguity around which
+      // group to insert into if there are consecutive groups.
+      group_inclusion =
+          BrowserRootView::DropIndex::GroupInclusion::kDontIncludeInGroup;
+    } else {
+      group_inclusion =
+          BrowserRootView::DropIndex::GroupInclusion::kIncludeInGroup;
+    }
   }
 
   if (position_hint == DragPositionHint::kBottom) {
diff --git a/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_link_drag_browsertest.cc b/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_link_drag_browsertest.cc
index 6a56c3c..4e76efe 100644
--- a/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_link_drag_browsertest.cc
+++ b/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_link_drag_browsertest.cc
@@ -237,6 +237,7 @@
 
 IN_PROC_BROWSER_TEST_F(VerticalTabStripLinkDragTest, DropInGroups) {
   EnsureTabCount(3);
+  auto tab_views = WaitForTabs(3);
   tab_strip_model()->AddToNewGroup({0, 1});
   RunScheduledLayouts();
 
@@ -262,6 +263,16 @@
     EXPECT_EQ(drop_index->group_inclusion,
               BrowserRootView::DropIndex::GroupInclusion::kIncludeInGroup);
   }
+
+  // Drop at the bottom of the last tab in the group -> ungrouped.
+  {
+    gfx::Point location(tab_views[1]->width() / 2, tab_views[1]->height() - 2);
+    auto drop_index = GetDropIndexAt(tab_views[1], location);
+    ASSERT_TRUE(drop_index.has_value());
+    EXPECT_EQ(drop_index->index, 2);
+    EXPECT_EQ(drop_index->group_inclusion,
+              BrowserRootView::DropIndex::GroupInclusion::kDontIncludeInGroup);
+  }
 }
 
 IN_PROC_BROWSER_TEST_F(VerticalTabStripLinkDragTest, DropInCollapsedGroups) {
diff --git a/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_scroll_bar.cc b/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_scroll_bar.cc
index 306bac9..4eec5e86 100644
--- a/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_scroll_bar.cc
+++ b/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_scroll_bar.cc
@@ -9,31 +9,32 @@
 #include "base/functional/bind.h"
 #include "base/i18n/rtl.h"
 #include "cc/paint/paint_flags.h"
+#include "chrome/browser/ui/tabs/vertical_tab_strip_state_controller.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "third_party/skia/include/core/SkPathBuilder.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/color/color_id.h"
 #include "ui/color/color_provider.h"
 #include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animator.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/gfx/canvas.h"
 #include "ui/native_theme/overlay_scrollbar_constants.h"
 #include "ui/views/background.h"
-#include "ui/views/border.h"
 #include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
 #include "ui/views/layout/fill_layout.h"
 
 namespace {
 
-// Total thickness of the thumb (matches visuals when hovered).
-constexpr int kThumbThickness = 10;
-constexpr int kThumbUnhoveredOffset = 5;
-constexpr int kThumbUnhoveredTrailingPadding = 2;
+// Total thickness of the thumb.
+constexpr int kThumbThickness = 5;
+constexpr int kThumbTrailingPadding = 4;
+constexpr int kCollapsedThumbTrailingPadding = 0;
 
 }  // namespace
 
 VerticalTabStripScrollBar::Thumb::Thumb(VerticalTabStripScrollBar* scroll_bar)
-    : views::BaseScrollBarThumb(scroll_bar) {
+    : views::BaseScrollBarThumb(scroll_bar), scroll_bar_(scroll_bar) {
   // |scroll_bar| isn't done being constructed; it's not safe to do anything
   // that might reference it yet.
 }
@@ -44,19 +45,16 @@
   SetFlipCanvasOnPaintForRTLUI(true);
   SetPaintToLayer();
   layer()->SetFillsBoundsOpaquely(false);
-  // Animate all changes to the layer except the first one.
-  OnStateChanged();
+  StartHideCountdown();
   layer()->SetAnimator(ui::LayerAnimator::CreateImplicitAnimator());
 }
 
 gfx::Size VerticalTabStripScrollBar::Thumb::CalculatePreferredSize(
     const views::SizeBounds& /*available_size*/) const {
-  // The visual size of the thumb is kThumbThickness, but it slides back and
-  // forth by thumb_hover_offset(). To make event targeting work well, expand
-  // the width of the thumb such that it's always taking up the full width of
-  // the track regardless of the offset.
-  return gfx::Size(kThumbThickness + kThumbUnhoveredOffset,
-                   kThumbThickness + kThumbUnhoveredOffset);
+  const int padding = scroll_bar_->tab_strip_collapsed_
+                          ? kCollapsedThumbTrailingPadding
+                          : kThumbTrailingPadding;
+  return gfx::Size(kThumbThickness + padding, kThumbThickness + padding);
 }
 
 void VerticalTabStripScrollBar::Thumb::OnPaint(gfx::Canvas* canvas) {
@@ -65,10 +63,9 @@
   fill_flags.setColor(GetColorProvider()->GetColor(ui::kColorSysStateDisabled));
   gfx::RectF fill_bounds(GetLocalBounds());
   fill_bounds.Inset(gfx::InsetsF::TLBR(
-      0, kThumbUnhoveredOffset, 0,
-      GetState() == views::Button::STATE_NORMAL
-          ? kThumbUnhoveredOffset + kThumbUnhoveredTrailingPadding
-          : 0));
+      0, 0, 0,
+      (scroll_bar_->tab_strip_collapsed_ ? kCollapsedThumbTrailingPadding
+                                         : kThumbTrailingPadding)));
   float rounded_corners = fill_bounds.width() / 2.0f;
   canvas->DrawRoundRect(fill_bounds, rounded_corners, fill_flags);
 }
@@ -76,24 +73,10 @@
 void VerticalTabStripScrollBar::Thumb::OnBoundsChanged(
     const gfx::Rect& previous_bounds) {
   Show();
-}
-
-void VerticalTabStripScrollBar::Thumb::OnStateChanged() {
+  // Don't start the hide countdown if the thumb is still hovered or pressed.
   if (GetState() == views::Button::STATE_NORMAL) {
-    gfx::Transform translation;
-    const int direction = base::i18n::IsRTL() ? -1 : 1;
-    translation.Translate(gfx::Vector2d(direction * kThumbUnhoveredOffset, 0));
-    layer()->SetTransform(translation);
-
-    if (GetWidget()) {
-      StartHideCountdown();
-    }
-  } else {
-    hide_timer_.Stop();
-    Show();
-    layer()->SetTransform(gfx::Transform());
+    StartHideCountdown();
   }
-  SchedulePaint();
 }
 
 void VerticalTabStripScrollBar::Thumb::Show() {
@@ -101,10 +84,6 @@
     layer()->SetOpacity(1.0f);
   }
   hide_timer_.Stop();
-  // Don't start the hide countdown if the thumb is still hovered or pressed.
-  if (GetState() == views::Button::STATE_NORMAL) {
-    StartHideCountdown();
-  }
 }
 
 void VerticalTabStripScrollBar::Thumb::Hide() {
@@ -124,21 +103,33 @@
 BEGIN_METADATA(VerticalTabStripScrollBar, Thumb)
 END_METADATA
 
-VerticalTabStripScrollBar::VerticalTabStripScrollBar()
-    : views::ScrollBar(views::ScrollBar::Orientation::kVertical) {
-  // Allow the thumb to take up the whole size of the scrollbar.  Layout need
-  // only set the thumb cross-axis coordinate; ScrollBar::Update() will set the
-  // thumb size/offset.
+VerticalTabStripScrollBar::VerticalTabStripScrollBar(
+    tabs::VerticalTabStripStateController* state_controller)
+    : views::ScrollBar(views::ScrollBar::Orientation::kVertical),
+      tab_strip_collapsed_(state_controller->IsCollapsed()) {
+  SetNotifyEnterExitOnChild(true);
   SetLayoutManager(std::make_unique<views::FillLayout>());
   auto* thumb = new Thumb(this);
   SetThumb(thumb);
   thumb->Init();
+  collapsed_state_changed_subscription_ =
+      state_controller->RegisterOnCollapseChanged(base::BindRepeating(
+          &VerticalTabStripScrollBar::OnCollapsedStateChanged,
+          base::Unretained(this)));
 }
 
 VerticalTabStripScrollBar::~VerticalTabStripScrollBar() = default;
 
-gfx::Insets VerticalTabStripScrollBar::GetInsets() const {
-  return gfx::Insets::TLBR(0, -kThumbUnhoveredOffset, 0, 0);
+void VerticalTabStripScrollBar::OnMouseEntered(const ui::MouseEvent& event) {
+  VerticalTabStripScrollBar::Thumb* thumb =
+      static_cast<VerticalTabStripScrollBar::Thumb*>(GetThumb());
+  thumb->Show();
+}
+
+void VerticalTabStripScrollBar::OnMouseExited(const ui::MouseEvent& event) {
+  VerticalTabStripScrollBar::Thumb* thumb =
+      static_cast<VerticalTabStripScrollBar::Thumb*>(GetThumb());
+  thumb->StartHideCountdown();
 }
 
 bool VerticalTabStripScrollBar::OverlapsContent() const {
@@ -150,7 +141,17 @@
 }
 
 int VerticalTabStripScrollBar::GetThickness() const {
-  return kThumbThickness;
+  return kThumbThickness + (tab_strip_collapsed_
+                                ? kCollapsedThumbTrailingPadding
+                                : kThumbTrailingPadding);
+}
+
+void VerticalTabStripScrollBar::OnCollapsedStateChanged(
+    tabs::VerticalTabStripStateController* state_controller) {
+  if (tab_strip_collapsed_ != state_controller->IsCollapsed()) {
+    tab_strip_collapsed_ = state_controller->IsCollapsed();
+    InvalidateLayout();
+  }
 }
 
 BEGIN_METADATA(VerticalTabStripScrollBar)
diff --git a/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_scroll_bar.h b/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_scroll_bar.h
index 4e206822..9705e55 100644
--- a/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_scroll_bar.h
+++ b/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_scroll_bar.h
@@ -5,11 +5,16 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_TABS_VERTICAL_VERTICAL_TAB_STRIP_SCROLL_BAR_H_
 #define CHROME_BROWSER_UI_VIEWS_TABS_VERTICAL_VERTICAL_TAB_STRIP_SCROLL_BAR_H_
 
+#include "base/callback_list.h"
 #include "base/memory/raw_ptr.h"
-#include "base/timer/timer.h"
+#include "chrome/browser/ui/tabs/vertical_tab_strip_state_controller.h"
 #include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
 #include "ui/views/controls/scrollbar/scroll_bar.h"
 
+namespace tabs {
+class VerticalTabStripStateController;
+}
+
 // The transparent vertical scrollbar which overlays its contents and expands on
 // hover. Used for the pinned and unpinned tab containers in the vertical tab
 // strip.
@@ -17,7 +22,8 @@
   METADATA_HEADER(VerticalTabStripScrollBar, ScrollBar)
 
  public:
-  VerticalTabStripScrollBar();
+  explicit VerticalTabStripScrollBar(
+      tabs::VerticalTabStripStateController* state_controller);
 
   VerticalTabStripScrollBar(const VerticalTabStripScrollBar&) = delete;
   VerticalTabStripScrollBar& operator=(const VerticalTabStripScrollBar&) =
@@ -26,7 +32,8 @@
   ~VerticalTabStripScrollBar() override;
 
   // ScrollBar:
-  gfx::Insets GetInsets() const override;
+  void OnMouseEntered(const ui::MouseEvent& event) override;
+  void OnMouseExited(const ui::MouseEvent& event) override;
   bool OverlapsContent() const override;
   gfx::Rect GetTrackBounds() const override;
   int GetThickness() const override;
@@ -45,11 +52,9 @@
 
     void Init();
 
-    // Shows this (effectively, the thumb) without delay.
     void Show();
-    // Hides this with a delay.
     void Hide();
-    // Starts a countdown that hides this when it fires.
+    // Starts a countdown that hides the thumb when it fires.
     void StartHideCountdown();
 
    protected:
@@ -58,11 +63,18 @@
         const views::SizeBounds& /*available_size*/) const override;
     void OnPaint(gfx::Canvas* canvas) override;
     void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
-    void OnStateChanged() override;
 
    private:
     base::OneShotTimer hide_timer_;
+    raw_ptr<VerticalTabStripScrollBar> scroll_bar_ = nullptr;
   };
+  friend class Thumb;
+
+  void OnCollapsedStateChanged(
+      tabs::VerticalTabStripStateController* state_controller);
+
+  bool tab_strip_collapsed_ = false;
+  base::CallbackListSubscription collapsed_state_changed_subscription_;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_TABS_VERTICAL_VERTICAL_TAB_STRIP_SCROLL_BAR_H_
diff --git a/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_view.cc b/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_view.cc
index 5353c33..8418b38 100644
--- a/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_view.cc
+++ b/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_view.cc
@@ -344,8 +344,9 @@
       views::ScrollView::ScrollBarMode::kDisabled);
   scroll_view->SetOverflowGradientMask(
       views::ScrollView::GradientDirection::kVertical);
-  scroll_view->SetVerticalScrollBar(
-      std::make_unique<VerticalTabStripScrollBar>());
+  CHECK(collection_node_);
+  scroll_view->SetVerticalScrollBar(std::make_unique<VerticalTabStripScrollBar>(
+      collection_node_->GetController()->GetStateController()));
   callback_subscriptions_.emplace_back(scroll_view->AddContentsScrolledCallback(
       base::BindRepeating(&VerticalTabStripView::HideHoverCardOnScroll,
                           base::Unretained(this))));
diff --git a/chrome/browser/ui/views/ui_devtools_browsertest.cc b/chrome/browser/ui/views/ui_devtools_browsertest.cc
new file mode 100644
index 0000000..5f02d11
--- /dev/null
+++ b/chrome/browser/ui/views/ui_devtools_browsertest.cc
@@ -0,0 +1,71 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/ui_devtools/devtools_server.h"
+#include "components/ui_devtools/switches.h"
+#include "components/ui_devtools/views/server_holder.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class UIDevToolsBrowserTest : public InProcessBrowserTest {
+ public:
+  UIDevToolsBrowserTest() = default;
+  ~UIDevToolsBrowserTest() override = default;
+
+  void SetUpDefaultCommandLine(base::CommandLine* command_line) override {
+    InProcessBrowserTest::SetUpDefaultCommandLine(command_line);
+    // Launch UI DevTools with port 0 (--enable-ui-devtools=0). This ensures the
+    // server listens on an available ephemeral port, avoiding "Address already
+    // in use" errors which were causing the test to fail/timeout.
+    command_line->AppendSwitchASCII(ui_devtools::switches::kEnableUiDevTools,
+                                    "0");
+  }
+};
+
+// Regression test for crbug.com/487264576. UI DevTools could not be connected
+// to due to a CSP rule in the DevTools frontend.
+IN_PROC_BROWSER_TEST_F(UIDevToolsBrowserTest, Connection) {
+  // Wait for the server to start.
+  const ui_devtools::UiDevToolsServer* server =
+      ui_devtools::ServerHolder::GetInstance()->GetUiDevToolsServerInstance();
+  ASSERT_TRUE(server);
+
+  // Construct the URL for the frontend.
+  // Use 127.0.0.1 as per the server implementation and the reported error.
+  std::string url_string = base::StringPrintf(
+      "devtools://devtools/bundled/"
+      "devtools_app.html?uiDevTools=true&ws=127.0.0.1:%d/0",
+      server->port());
+  GURL url(url_string);
+
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  content::WebContentsConsoleObserver console_observer(web_contents);
+  console_observer.SetPattern("*Content Security Policy*");
+
+  base::RunLoop run_loop;
+  const_cast<ui_devtools::UiDevToolsServer*>(server)
+      ->SetOnClientConnectedForTesting(run_loop.QuitClosure());
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
+
+  run_loop.Run();
+
+  // If the connection violates CSP, an error will be logged to the console.
+  if (!console_observer.messages().empty()) {
+    FAIL() << "CSP violation detected: " << console_observer.GetMessageAt(0);
+  }
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc
index 13df301..2bfc577 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc
@@ -7132,35 +7132,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Gardeners: Disabling this test is supported.
-  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
-  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
-  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed(Site::kStandalone);
-  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
-  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
-                                           IsShown::kNotShown);
-  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
-                                     Site::kStandaloneMigratedSuggested);
-  helper_.CheckMenuButtonPendingUpdate(
-      MenuButtonState::kExpandedUpdateAvailable);
-  helper_.CheckAppNotInList(Site::kStandaloneMigratedSuggested);
-  helper_.TriggerUpdateDialogAndHandleResponse(
-      UpdateDialogResponse::kAcceptUpdate);
-  helper_.CheckAppNotInList(Site::kStandalone);
-  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedSuggested);
-  helper_.CheckAppTitle(Site::kStandaloneMigratedSuggested,
-                        Title::kStandaloneMigratedSuggested);
-  helper_.CheckAppIcon(Site::kStandaloneMigratedSuggested, Color::kRed);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseCancelDialogAndUninstall) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -7187,34 +7158,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Gardeners: Disabling this test is supported.
-  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
-  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
-  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed(Site::kStandalone);
-  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
-  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
-                                           IsShown::kNotShown);
-  helper_.NavigateBrowser(Site::kStandaloneMigratedSuggested);
-  helper_.CheckMenuButtonPendingUpdate(
-      MenuButtonState::kExpandedUpdateAvailable);
-  helper_.CheckAppNotInList(Site::kStandaloneMigratedSuggested);
-  helper_.TriggerUpdateDialogAndHandleResponse(
-      UpdateDialogResponse::kAcceptUpdate);
-  helper_.CheckAppNotInList(Site::kStandalone);
-  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedSuggested);
-  helper_.CheckAppTitle(Site::kStandaloneMigratedSuggested,
-                        Title::kStandaloneMigratedSuggested);
-  helper_.CheckAppIcon(Site::kStandaloneMigratedSuggested, Color::kRed);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseCancelDialogAndUninstall) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -7240,34 +7183,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Gardeners: Disabling this test is supported.
-  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
-  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
-  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed(Site::kStandalone);
-  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
-  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
-                                           IsShown::kNotShown);
-  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedSuggested);
-  helper_.CheckMenuButtonPendingUpdate(
-      MenuButtonState::kExpandedUpdateAvailable);
-  helper_.CheckAppNotInList(Site::kStandaloneMigratedSuggested);
-  helper_.TriggerUpdateDialogAndHandleResponse(
-      UpdateDialogResponse::kAcceptUpdate);
-  helper_.CheckAppNotInList(Site::kStandalone);
-  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedSuggested);
-  helper_.CheckAppTitle(Site::kStandaloneMigratedSuggested,
-                        Title::kStandaloneMigratedSuggested);
-  helper_.CheckAppIcon(Site::kStandaloneMigratedSuggested, Color::kRed);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseCancelDialogAndUninstall) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -7293,35 +7208,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Gardeners: Disabling this test is supported.
-  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
-  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
-  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed(Site::kStandalone);
-  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
-  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
-                                           IsShown::kNotShown);
-  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
-                                     Site::kStandaloneMigratedForced);
-  helper_.CheckMenuButtonPendingUpdate(
-      MenuButtonState::kExpandedUpdateAvailable);
-  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
-  helper_.TriggerUpdateDialogAndHandleResponse(
-      UpdateDialogResponse::kAcceptUpdate);
-  helper_.CheckAppNotInList(Site::kStandalone);
-  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
-  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
-                        Title::kStandaloneMigratedForced);
-  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kRed);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseCancelDialogAndUninstall) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -7348,34 +7234,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Gardeners: Disabling this test is supported.
-  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
-  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
-  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed(Site::kStandalone);
-  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
-  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
-                                           IsShown::kNotShown);
-  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
-  helper_.CheckMenuButtonPendingUpdate(
-      MenuButtonState::kExpandedUpdateAvailable);
-  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
-  helper_.TriggerUpdateDialogAndHandleResponse(
-      UpdateDialogResponse::kAcceptUpdate);
-  helper_.CheckAppNotInList(Site::kStandalone);
-  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
-  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
-                        Title::kStandaloneMigratedForced);
-  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kRed);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseCancelDialogAndUninstall) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -7401,34 +7259,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Gardeners: Disabling this test is supported.
-  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
-  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
-  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed(Site::kStandalone);
-  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
-  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
-                                           IsShown::kNotShown);
-  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
-  helper_.CheckMenuButtonPendingUpdate(
-      MenuButtonState::kExpandedUpdateAvailable);
-  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
-  helper_.TriggerUpdateDialogAndHandleResponse(
-      UpdateDialogResponse::kAcceptUpdate);
-  helper_.CheckAppNotInList(Site::kStandalone);
-  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
-  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
-                        Title::kStandaloneMigratedForced);
-  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kRed);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseCancelDialogAndUninstall) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -7454,35 +7284,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Gardeners: Disabling this test is supported.
-  helper_.InstallMenuOption(Site::kStandalone);
-  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
-  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed(Site::kStandalone);
-  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
-  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
-                                           IsShown::kNotShown);
-  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
-                                     Site::kStandaloneMigratedSuggested);
-  helper_.CheckMenuButtonPendingUpdate(
-      MenuButtonState::kExpandedUpdateAvailable);
-  helper_.CheckAppNotInList(Site::kStandaloneMigratedSuggested);
-  helper_.TriggerUpdateDialogAndHandleResponse(
-      UpdateDialogResponse::kAcceptUpdate);
-  helper_.CheckAppNotInList(Site::kStandalone);
-  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedSuggested);
-  helper_.CheckAppTitle(Site::kStandaloneMigratedSuggested,
-                        Title::kStandaloneMigratedSuggested);
-  helper_.CheckAppIcon(Site::kStandaloneMigratedSuggested, Color::kRed);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseCancelDialogAndUninstall) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -7509,34 +7310,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Gardeners: Disabling this test is supported.
-  helper_.InstallMenuOption(Site::kStandalone);
-  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
-  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed(Site::kStandalone);
-  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
-  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
-                                           IsShown::kNotShown);
-  helper_.NavigateBrowser(Site::kStandaloneMigratedSuggested);
-  helper_.CheckMenuButtonPendingUpdate(
-      MenuButtonState::kExpandedUpdateAvailable);
-  helper_.CheckAppNotInList(Site::kStandaloneMigratedSuggested);
-  helper_.TriggerUpdateDialogAndHandleResponse(
-      UpdateDialogResponse::kAcceptUpdate);
-  helper_.CheckAppNotInList(Site::kStandalone);
-  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedSuggested);
-  helper_.CheckAppTitle(Site::kStandaloneMigratedSuggested,
-                        Title::kStandaloneMigratedSuggested);
-  helper_.CheckAppIcon(Site::kStandaloneMigratedSuggested, Color::kRed);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseCancelDialogAndUninstall) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -7562,34 +7335,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Gardeners: Disabling this test is supported.
-  helper_.InstallMenuOption(Site::kStandalone);
-  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
-  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed(Site::kStandalone);
-  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
-  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
-                                           IsShown::kNotShown);
-  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedSuggested);
-  helper_.CheckMenuButtonPendingUpdate(
-      MenuButtonState::kExpandedUpdateAvailable);
-  helper_.CheckAppNotInList(Site::kStandaloneMigratedSuggested);
-  helper_.TriggerUpdateDialogAndHandleResponse(
-      UpdateDialogResponse::kAcceptUpdate);
-  helper_.CheckAppNotInList(Site::kStandalone);
-  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedSuggested);
-  helper_.CheckAppTitle(Site::kStandaloneMigratedSuggested,
-                        Title::kStandaloneMigratedSuggested);
-  helper_.CheckAppIcon(Site::kStandaloneMigratedSuggested, Color::kRed);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseCancelDialogAndUninstall) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -7615,35 +7360,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Gardeners: Disabling this test is supported.
-  helper_.InstallMenuOption(Site::kStandalone);
-  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
-  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed(Site::kStandalone);
-  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
-  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
-                                           IsShown::kNotShown);
-  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
-                                     Site::kStandaloneMigratedForced);
-  helper_.CheckMenuButtonPendingUpdate(
-      MenuButtonState::kExpandedUpdateAvailable);
-  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
-  helper_.TriggerUpdateDialogAndHandleResponse(
-      UpdateDialogResponse::kAcceptUpdate);
-  helper_.CheckAppNotInList(Site::kStandalone);
-  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
-  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
-                        Title::kStandaloneMigratedForced);
-  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kRed);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseCancelDialogAndUninstall) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -7670,34 +7386,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Gardeners: Disabling this test is supported.
-  helper_.InstallMenuOption(Site::kStandalone);
-  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
-  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed(Site::kStandalone);
-  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
-  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
-                                           IsShown::kNotShown);
-  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
-  helper_.CheckMenuButtonPendingUpdate(
-      MenuButtonState::kExpandedUpdateAvailable);
-  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
-  helper_.TriggerUpdateDialogAndHandleResponse(
-      UpdateDialogResponse::kAcceptUpdate);
-  helper_.CheckAppNotInList(Site::kStandalone);
-  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
-  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
-                        Title::kStandaloneMigratedForced);
-  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kRed);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseCancelDialogAndUninstall) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -7723,34 +7411,6 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
-    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Gardeners: Disabling this test is supported.
-  helper_.InstallMenuOption(Site::kStandalone);
-  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
-  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
-  helper_.CheckWindowCreated();
-  helper_.CheckAppInListWindowed(Site::kStandalone);
-  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
-  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
-                                           IsShown::kNotShown);
-  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
-  helper_.CheckMenuButtonPendingUpdate(
-      MenuButtonState::kExpandedUpdateAvailable);
-  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
-  helper_.TriggerUpdateDialogAndHandleResponse(
-      UpdateDialogResponse::kAcceptUpdate);
-  helper_.CheckAppNotInList(Site::kStandalone);
-  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
-  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
-                        Title::kStandaloneMigratedForced);
-  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kRed);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
     WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseCancelDialogAndUninstall) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
@@ -7774,5 +7434,2609 @@
   helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
 }
 
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallPolicyAppStandaloneWithShortcutWindowedWebApp_LaunchFromChromeAppsStandalone_NavigateBrowserStandaloneMigratedSuggested) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kStandalone, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedSuggested);
+  helper_.CheckMenuButtonPendingUpdate(MenuButtonState::kNotExpanded);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallPolicyAppStandaloneWithShortcutWindowedWebApp_LaunchFromChromeAppsStandalone_NavigatePwaStandaloneStandaloneMigratedSuggested) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kStandalone, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedSuggested);
+  helper_.CheckMenuButtonPendingUpdate(MenuButtonState::kNotExpanded);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallPolicyAppStandaloneWithShortcutWindowedWebApp_LaunchFromChromeAppsStandalone_NavigateBrowserStandaloneMigratedForced) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kStandalone, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(MenuButtonState::kNotExpanded);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallPolicyAppStandaloneWithShortcutWindowedWebApp_LaunchFromChromeAppsStandalone_NavigatePwaStandaloneStandaloneMigratedForced) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kStandalone, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(MenuButtonState::kNotExpanded);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallPolicyAppStandaloneWithShortcutWindowedWebApp_LaunchFromChromeAppsStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedSuggested) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kStandalone, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedSuggested);
+  helper_.CheckMenuButtonPendingUpdate(MenuButtonState::kNotExpanded);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallPolicyAppStandaloneWithShortcutWindowedWebApp_LaunchFromChromeAppsStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallPolicyApp(Site::kStandalone, ShortcutOptions::kWithShortcut,
+                           WindowOptions::kWindowed, InstallMode::kWebApp);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckWindowCreated();
+  helper_.CheckWindowDisplayStandalone();
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(MenuButtonState::kNotExpanded);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedSuggested);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedSuggested);
+  helper_.TriggerUpdateDialogAndHandleResponse(
+      UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedSuggested,
+                                Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedSuggested);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedSuggested,
+                        Title::kStandaloneMigratedSuggested);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedSuggested, Color::kRed);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedSuggested);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedSuggested);
+  helper_.TriggerUpdateDialogAndHandleResponse(
+      UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedSuggested,
+                                Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedSuggested);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedSuggested,
+                        Title::kStandaloneMigratedSuggested);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedSuggested, Color::kRed);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedSuggested);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedSuggested);
+  helper_.TriggerUpdateDialogAndHandleResponse(
+      UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedSuggested,
+                                Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedSuggested);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedSuggested,
+                        Title::kStandaloneMigratedSuggested);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedSuggested, Color::kRed);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.TriggerUpdateDialogAndHandleResponse(
+      UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneMigratedForced);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kRed);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.TriggerUpdateDialogAndHandleResponse(
+      UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneMigratedForced);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kRed);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.TriggerUpdateDialogAndHandleResponse(
+      UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneMigratedForced);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kRed);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedSuggested);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedSuggested);
+  helper_.TriggerUpdateDialogAndHandleResponse(
+      UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedSuggested,
+                                Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedSuggested);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedSuggested,
+                        Title::kStandaloneMigratedSuggested);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedSuggested, Color::kRed);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedSuggested);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedSuggested);
+  helper_.TriggerUpdateDialogAndHandleResponse(
+      UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedSuggested,
+                                Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedSuggested);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedSuggested,
+                        Title::kStandaloneMigratedSuggested);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedSuggested, Color::kRed);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedSuggested_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedSuggested);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedSuggested);
+  helper_.TriggerUpdateDialogAndHandleResponse(
+      UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedSuggested,
+                                Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedSuggested);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedSuggested,
+                        Title::kStandaloneMigratedSuggested);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedSuggested, Color::kRed);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.TriggerUpdateDialogAndHandleResponse(
+      UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneMigratedForced);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kRed);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.TriggerUpdateDialogAndHandleResponse(
+      UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneMigratedForced);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kRed);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_TriggerUpdateDialogAndHandleResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.TriggerUpdateDialogAndHandleResponse(
+      UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneMigratedForced);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kRed);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromMenuOptionStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromMenuOption(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromLaunchIconStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromLaunchIcon(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromChromeAppsStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromChromeApps(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
 }  // namespace
 }  // namespace web_app::integration_tests
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
index e4c77e52..72261196 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
@@ -8758,5 +8758,709 @@
   helper_.CheckAppIcon(Site::kStandalone, Color::kRed);
 }
 
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCancelDialogAndUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndUninstall);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseAcceptUpdate) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kAcceptUpdate);
+  helper_.CheckAppNotInList(Site::kStandalone);
+  helper_.CheckPwaWindowCreated(Site::kStandaloneMigratedForced, Number::kOne);
+  helper_.CheckAppInListWindowed(Site::kStandaloneMigratedForced);
+  helper_.CheckAppTitle(Site::kStandaloneMigratedForced,
+                        Title::kStandaloneOriginal);
+  helper_.CheckAppIcon(Site::kStandaloneMigratedForced, Color::kGreen);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCancelDialogAndCancelUninstall) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(
+      UpdateDialogResponse::kCancelDialogAndCancelUninstall);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallOmniboxIconStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallOmniboxIcon(InstallableSite::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_ManifestUpdateAddMigrateToStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.ManifestUpdateAddMigrateTo(Site::kStandalone,
+                                     Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigateBrowserStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigateBrowser(Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
+    WAI_InstallMenuStandalone_NavigatePwaStandaloneStandaloneMigratedForced_ClosePwa_LaunchFromPlatformShortcutStandalone_HandleUpdateDialogResponseCloseDialog) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Gardeners: Disabling this test is supported.
+  helper_.InstallMenuOption(Site::kStandalone);
+  helper_.CheckAppIcon(Site::kStandalone, Color::kGreen);
+  helper_.CheckAppTitle(Site::kStandalone, Title::kStandaloneOriginal);
+  helper_.CheckWindowCreated();
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckPlatformShortcutAndIcon(Site::kStandalone);
+  helper_.CheckWindowControlsOverlayToggle(Site::kStandalone,
+                                           IsShown::kNotShown);
+  helper_.NavigatePwa(Site::kStandalone, Site::kStandaloneMigratedForced);
+  helper_.CheckMenuButtonPendingUpdate(
+      MenuButtonState::kExpandedUpdateAvailable);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.ClosePwa();
+  helper_.LaunchFromPlatformShortcut(Site::kStandalone);
+  helper_.CheckUpdateDialogIsShowing();
+  helper_.HandleUpdateDialogResponse(UpdateDialogResponse::kCloseDialog);
+  helper_.CheckAppNotInList(Site::kStandaloneMigratedForced);
+  helper_.CheckAppInListWindowed(Site::kStandalone);
+  helper_.CheckWindowClosed();
+}
+
 }  // namespace
 }  // namespace web_app::integration_tests
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
index c40dc39d..d473a516 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -1044,6 +1044,12 @@
   in_tear_down_ = true;
   LOG(INFO) << "TearDownOnMainThread: Start.";
 
+  // Print debug information if there was a failure.
+  if (testing::Test::HasFailure()) {
+    base::TimeDelta log_time = base::TimeTicks::Now() - start_time_;
+    test::LogDebugInfoToConsole(GetAllProfiles(), log_time);
+  }
+
 #if BUILDFLAG(IS_CHROMEOS)
   if (delegate_->IsSyncTest()) {
     SyncTurnOff();
@@ -1100,12 +1106,6 @@
   override_registration_.reset();
 
   LOG(INFO) << "TearDownOnMainThread: Complete.";
-
-  // Print debug information if there was a failure.
-  if (testing::Test::HasFailure()) {
-    base::TimeDelta log_time = base::TimeTicks::Now() - start_time_;
-    test::LogDebugInfoToConsole(GetAllProfiles(), log_time);
-  }
 }
 
 void WebAppIntegrationTestDriver::OnWidgetShown(views::Widget* widget) {
@@ -1172,7 +1172,21 @@
       views::test::AcceptDialog(uninstall_dialog_widget);
       uninstall_destroyed.Wait();
     } break;
-    case UpdateDialogResponse::kIgnoreDialog:
+    case UpdateDialogResponse::kCancelDialogAndCancelUninstall: {
+      auto uninstall_dialog_view =
+          std::make_unique<views::NamedWidgetShownWaiter>(
+              views::test::AnyWidgetTestPasskey{},
+              "WebAppUninstallDialogDelegateView");
+      views::test::CancelDialog(manifest_update_widget);
+      views::Widget* uninstall_dialog_widget = uninstall_dialog_widget =
+          uninstall_dialog_view->WaitIfNeededAndGet();
+      ASSERT_NE(uninstall_dialog_widget, nullptr);
+      views::test::WidgetDestroyedWaiter uninstall_destroyed(
+          uninstall_dialog_widget);
+      views::test::CancelDialog(uninstall_dialog_widget);
+      uninstall_destroyed.Wait();
+    } break;
+    case UpdateDialogResponse::kIgnoreDialog: {
       views::test::WidgetDestroyedWaiter destroyed_waiter(
           manifest_update_widget);
       views::ElementTrackerViews* tracker_views =
@@ -1186,6 +1200,13 @@
       ASSERT_NE(nullptr, button);
       views::test::ButtonTestApi(button).NotifyClick(ui::test::TestEvent());
       destroyed_waiter.Wait();
+    } break;
+    case UpdateDialogResponse::kCloseDialog: {
+      views::test::WidgetDestroyedWaiter destroyed_waiter(
+          manifest_update_widget);
+      manifest_update_widget->Close();
+      destroyed_waiter.Wait();
+    } break;
   }
   // Wait for the pending update to be applied, or the uninstall command to
   // finish running.
@@ -2452,10 +2473,14 @@
     return;
   }
 
+  webapps::AppId app_id = GetAppIdBySiteMode(app);
   GURL url =
       GetUrlForSite(app, GetMigrateToConfiguration(to).manifest_url_param);
-  ForceUpdateManifestContents(app, url,
-                              /*wait_for_pending_updates_to_arrive=*/true);
+  ForceUpdateManifestContents(
+      app, url,
+      /*wait_for_pending_updates_to_arrive=*/
+      provider()->registrar_unsafe().AppMatches(
+          app_id, WebAppFilter::IsAppValidMigrationSource()));
 
   AfterStateChangeAction();
 }
@@ -3791,12 +3816,12 @@
   int after_state_app_window_count = 0;
   webapps::AppId app_id = GetAppIdBySiteMode(site);
   for (const auto& browser_pair : before_action_profile->browsers) {
-    if (AppBrowserController::IsForWebApp(browser_pair.first, app_id)) {
+    if (browser_pair.second.app_id == app_id) {
       before_state_app_window_count++;
     }
   }
   for (const auto& browser_pair : after_action_profile->browsers) {
-    if (AppBrowserController::IsForWebApp(browser_pair.first, app_id)) {
+    if (browser_pair.second.app_id == app_id) {
       after_state_app_window_count++;
     }
   }
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h
index 82b17173..4b47955c 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h
@@ -146,7 +146,9 @@
 enum class UpdateDialogResponse {
   kAcceptUpdate,
   kCancelDialogAndUninstall,
+  kCancelDialogAndCancelUninstall,
   kIgnoreDialog,
+  kCloseDialog,
 };
 
 enum class SubAppInstallDialogOptions {
diff --git a/chrome/browser/ui/webui/BUILD.gn b/chrome/browser/ui/webui/BUILD.gn
index de12450..b43467b 100644
--- a/chrome/browser/ui/webui/BUILD.gn
+++ b/chrome/browser/ui/webui/BUILD.gn
@@ -45,6 +45,7 @@
 
   deps = [
     ":webui",
+    "//chrome/browser/actor/ui:actor_overlay",
     "//chrome/browser/optimization_guide",
     "//chrome/browser/ui",
     "//chrome/browser/ui/webui/about",
@@ -68,10 +69,15 @@
     deps += [ "//chrome/browser/ui/webui/signin:inline_login" ]
   }
 
+  if (enable_glic) {
+    if (!is_android) {
+      deps += [ "//chrome/browser/glic/selection" ]
+    }
+  }
   if (!is_android) {
     deps += [
       "//chrome/browser/actor/ui",
-      "//chrome/browser/actor/ui:actor_overlay",
+      "//chrome/browser/actor/ui:actor_overlay_web_view",
       "//chrome/browser/contextual_tasks:ui",
       "//chrome/browser/ui/webui/access_code_cast",
       "//chrome/browser/ui/webui/app_service_internals",
diff --git a/chrome/browser/ui/webui/chrome_untrusted_web_ui_configs.cc b/chrome/browser/ui/webui/chrome_untrusted_web_ui_configs.cc
index cfc1610..a9caa48 100644
--- a/chrome/browser/ui/webui/chrome_untrusted_web_ui_configs.cc
+++ b/chrome/browser/ui/webui/chrome_untrusted_web_ui_configs.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/webui/chrome_untrusted_web_ui_configs.h"
 
 #include "build/build_config.h"
+#include "chrome/common/buildflags.h"
 #include "content/public/browser/webui_config_map.h"
 #include "printing/buildflags/buildflags.h"
 
@@ -17,6 +18,9 @@
 #endif  // BUILDFLAG(ENABLE_COMPOSE)
 #include "chrome/browser/ui/lens/lens_overlay_untrusted_ui.h"
 #include "chrome/browser/ui/lens/lens_side_panel_untrusted_ui.h"
+#if BUILDFLAG(ENABLE_GLIC)
+#include "chrome/browser/glic/selection/selection_overlay_untrusted_ui.h"
+#endif
 #endif  // defined(TOOLKIT_VIEWS)
 
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
@@ -54,6 +58,12 @@
 #if BUILDFLAG(ENABLE_COMPOSE)
   map.AddUntrustedWebUIConfig(std::make_unique<ComposeUIUntrustedConfig>());
 #endif  // BUILDFLAG(ENABLE_COMPOSE)
+
+#if BUILDFLAG(ENABLE_GLIC)
+  map.AddUntrustedWebUIConfig(
+      std::make_unique<glic::SelectionOverlayUntrustedUIConfig>());
+#endif  // BUILDFLAG(ENABLE_GLIC)
+
 #endif  // defined(TOOLKIT_VIEWS)
 
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
diff --git a/chrome/browser/ui/webui/cr_components/searchbox/BUILD.gn b/chrome/browser/ui/webui/cr_components/searchbox/BUILD.gn
index 48788b8..eb42ad8 100644
--- a/chrome/browser/ui/webui/cr_components/searchbox/BUILD.gn
+++ b/chrome/browser/ui/webui/cr_components/searchbox/BUILD.gn
@@ -47,6 +47,7 @@
     "//chrome/browser/contextual_tasks",
     "//chrome/browser/contextual_tasks:ui",
     "//chrome/browser/omnibox",
+    "//chrome/browser/predictors",
     "//chrome/browser/preloading",
     "//chrome/browser/preloading/search_preload",
     "//chrome/browser/profiles:profile",
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc
index 03fe42d..a68192c5 100644
--- a/chrome/browser/ui/webui/extensions/extensions_ui.cc
+++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -374,6 +374,7 @@
       {"setShortcutInSystemSettings",
        IDS_EXTENSIONS_SET_SHORTCUT_IN_SYSTEM_SETTINGS},
       {"shortcutNotSet", IDS_SHORTCUT_NOT_SET},
+      {"shortcutClear", IDS_SHORTCUT_CLEAR},
       {"shortcutScopeGlobal", IDS_EXTENSIONS_SHORTCUT_SCOPE_GLOBAL},
       {"shortcutScopeLabel", IDS_EXTENSIONS_SHORTCUT_SCOPE_LABEL},
       {"shortcutScopeInChrome", IDS_EXTENSIONS_SHORTCUT_SCOPE_IN_CHROME},
diff --git a/chrome/browser/ui/webui/new_tab_page/action_chips/action_chips_generator.cc b/chrome/browser/ui/webui/new_tab_page/action_chips/action_chips_generator.cc
index fac1359..73db0c8c 100644
--- a/chrome/browser/ui/webui/new_tab_page/action_chips/action_chips_generator.cc
+++ b/chrome/browser/ui/webui/new_tab_page/action_chips/action_chips_generator.cc
@@ -248,17 +248,19 @@
 
 std::vector<omnibox::ToolMode> GetAllowedTools(
     const AimEligibilityService* aim_eligibility_service) {
-  std::vector<omnibox::ToolMode> allowed_tools;
+  std::vector<omnibox::ToolMode> tools;
   if (aim_eligibility_service == nullptr) {
-    return allowed_tools;
+    return tools;
   }
-  if (aim_eligibility_service->IsDeepSearchEligible()) {
-    allowed_tools.push_back(omnibox::TOOL_MODE_DEEP_SEARCH);
+  const omnibox::SearchboxConfig* searchbox_config =
+      aim_eligibility_service->GetSearchboxConfig();
+  if (!searchbox_config->has_rule_set()) {
+    return tools;
   }
-  if (aim_eligibility_service->IsCreateImagesEligible()) {
-    allowed_tools.push_back(omnibox::TOOL_MODE_IMAGE_GEN);
+  for (const int tool : searchbox_config->rule_set().allowed_tools()) {
+    tools.push_back(static_cast<omnibox::ToolMode>(tool));
   }
-  return allowed_tools;
+  return tools;
 }
 
 TabInfoPtr CreateTabInfo(const TabIdGenerator& tab_id_generator,
diff --git a/chrome/browser/ui/webui/new_tab_page/action_chips/action_chips_generator_unittest.cc b/chrome/browser/ui/webui/new_tab_page/action_chips/action_chips_generator_unittest.cc
index a8c23c1..09473e8 100644
--- a/chrome/browser/ui/webui/new_tab_page/action_chips/action_chips_generator_unittest.cc
+++ b/chrome/browser/ui/webui/new_tab_page/action_chips/action_chips_generator_unittest.cc
@@ -75,6 +75,8 @@
 using ::testing::TypedEq;
 using ::testing::WithArg;
 
+using enum omnibox::ToolMode;
+
 struct CreateSuggestionOptions {
   std::optional<omnibox::GroupId> group_id;
   int32_t icon_type = omnibox::SuggestTemplateInfo::ICON_TYPE_UNSPECIFIED;
@@ -246,6 +248,8 @@
 
     ON_CALL(*fake_client_, IsPersonalizedUrlDataCollectionActive())
         .WillByDefault(Return(true));
+
+    set_searchbox_config({TOOL_MODE_DEEP_SEARCH, TOOL_MODE_IMAGE_GEN});
     ON_CALL(*mock_aim_eligibility_service_, IsDeepSearchEligible)
         .WillByDefault(Return(true));
     ON_CALL(*mock_aim_eligibility_service_, IsCreateImagesEligible)
@@ -283,6 +287,13 @@
     return *mock_aim_eligibility_service_;
   }
 
+  void set_searchbox_config(base::span<const omnibox::ToolMode> allowed_tools) {
+    mock_aim_eligibility_service_->config()
+        .mutable_rule_set()
+        ->mutable_allowed_tools()
+        ->Assign(allowed_tools.begin(), allowed_tools.end());
+  }
+
   // Makes the optimization guide's mock permissive. i.e., after the call to
   // this method, the mock considers any URL as EDU vertical.
   void MakeOptimizationGuidePermissive() {
@@ -1233,12 +1244,7 @@
   GeneratorFixture generator_fixture;
 
   // Only Deep Search is eligible.
-  EXPECT_CALL(generator_fixture.mock_aim_eligibility_service(),
-              IsDeepSearchEligible())
-      .WillRepeatedly(Return(true));
-  EXPECT_CALL(generator_fixture.mock_aim_eligibility_service(),
-              IsCreateImagesEligible())
-      .WillRepeatedly(Return(false));
+  generator_fixture.set_searchbox_config({TOOL_MODE_DEEP_SEARCH});
 
   EXPECT_CALL(
       generator_fixture.mock_service(),
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
index efff83a..72c7561 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
@@ -803,7 +803,9 @@
 int NewTabPageUI::instance_count_ = 0;
 
 NewTabPageUI::NewTabPageUI(content::WebUI* web_ui)
-    : ui::MojoWebUIController(web_ui, /*enable_chrome_send=*/true),
+    : ui::MojoWebUIController(web_ui,
+                              /*enable_chrome_send=*/true,
+                              /*enable_chrome_histograms=*/true),
       content::WebContentsObserver(web_ui->GetWebContents()),
       page_factory_receiver_(this),
       customize_buttons_factory_receiver_(this),
diff --git a/chrome/browser/ui/webui/omnibox_popup/omnibox_popup_ui.cc b/chrome/browser/ui/webui/omnibox_popup/omnibox_popup_ui.cc
index 9bd2de3a..6d607ce6 100644
--- a/chrome/browser/ui/webui/omnibox_popup/omnibox_popup_ui.cc
+++ b/chrome/browser/ui/webui/omnibox_popup/omnibox_popup_ui.cc
@@ -71,7 +71,8 @@
 
 OmniboxPopupUI::OmniboxPopupUI(content::WebUI* web_ui)
     : TopChromeWebUIController(web_ui,
-                               true /* Needed for webui browser tests */),
+                               /*enable_chrome_send=*/true,
+                               /*enable_chrome_histograms=*/true),
       profile_(Profile::FromWebUI(web_ui)) {
   content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
       Profile::FromWebUI(web_ui), chrome::kChromeUIOmniboxPopupHost);
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 6391b8cf..eaa0486 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -824,6 +824,8 @@
       {"glicKeyboardShortcut", IDS_SETTINGS_GLIC_KEYBOARD_SHORTCUT},
       {"glicKeyboardShortcutEditLabel",
        IDS_SETTINGS_GLIC_KEYBOARD_SHORTCUT_EDIT_LABEL},
+      {"glicKeyboardShortcutClearLabel",
+       IDS_SETTINGS_GLIC_KEYBOARD_SHORTCUT_CLEAR_LABEL},
       {"glicKeyboardShortcutSublabel",
        IDS_SETTINGS_GLIC_KEYBOARD_SHORTCUT_SUBLABEL},
       {"glicKeyboardShortcutLearnMoreLabel",
@@ -831,6 +833,8 @@
       {"glicNavigationShortcut", IDS_SETTINGS_GLIC_NAVIGATION_SHORTCUT},
       {"glicNavigationShortcutEditLabel",
        IDS_SETTINGS_GLIC_NAVIGATION_SHORTCUT_EDIT_LABEL},
+      {"glicNavigationShortcutClearLabel",
+       IDS_SETTINGS_GLIC_NAVIGATION_SHORTCUT_CLEAR_LABEL},
       {"glicNavigationShortcutSublabel",
        IDS_SETTINGS_GLIC_NAVIGATION_SHORTCUT_SUBLABEL},
       {"glicKeyboardShortcutLearnMoreAriaLabel",
@@ -4183,6 +4187,7 @@
       {"shortcutNeedCharacter", IDS_SHORTCUT_NEED_CHARACTER},
       {"shortcutSet", IDS_SHORTCUT_SET},
       {"shortcutNotSet", IDS_SHORTCUT_NOT_SET},
+      {"shortcutClear", IDS_SHORTCUT_CLEAR},
       {"shortcutTypeAShortcut", IDS_TYPE_A_SHORTCUT},
   };
   html_source->AddLocalizedStrings(kShortcutInputStrings);
diff --git a/chrome/browser/ui/webui/skills/skills_dialog_view.cc b/chrome/browser/ui/webui/skills/skills_dialog_view.cc
index b9c31b7..73f16af 100644
--- a/chrome/browser/ui/webui/skills/skills_dialog_view.cc
+++ b/chrome/browser/ui/webui/skills/skills_dialog_view.cc
@@ -13,6 +13,7 @@
 #include "ui/base/interaction/element_identifier.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/layer.h"
+#include "ui/compositor/layer_type.h"
 #include "ui/gfx/geometry/rounded_corners_f.h"
 #include "ui/views/controls/webview/webview.h"
 #include "ui/views/layout/fill_layout.h"
@@ -24,8 +25,9 @@
 
 constexpr float kCornerRadius = 12.0f;
 constexpr int kWebViewWidth = 448;
-constexpr int kWebViewMinHeight = 471;
-constexpr int kWebViewMaxHeight = 503;  // Extra space needed for save error.
+constexpr int kWebViewMinHeight = 442;
+constexpr int kWebViewMaxHeight = 516;  // Extra space needed for errors and
+                                        // multi-line user account info.
 gfx::Size kWebViewMinSize = gfx::Size(kWebViewWidth, kWebViewMinHeight);
 gfx::Size kWebViewMaxSize = gfx::Size(kWebViewWidth, kWebViewMaxHeight);
 }  // namespace
diff --git a/chrome/browser/ui/webui/top_chrome/untrusted_top_chrome_web_ui_controller.cc b/chrome/browser/ui/webui/top_chrome/untrusted_top_chrome_web_ui_controller.cc
index b8c0c370..8bfdd3c 100644
--- a/chrome/browser/ui/webui/top_chrome/untrusted_top_chrome_web_ui_controller.cc
+++ b/chrome/browser/ui/webui/top_chrome/untrusted_top_chrome_web_ui_controller.cc
@@ -9,8 +9,11 @@
 
 UntrustedTopChromeWebUIController::UntrustedTopChromeWebUIController(
     content::WebUI* web_ui,
-    bool enable_chrome_send)
-    : TopChromeWebUIController(web_ui, enable_chrome_send) {
+    bool enable_chrome_send,
+    bool enable_chrome_histograms)
+    : TopChromeWebUIController(web_ui,
+                               enable_chrome_send,
+                               enable_chrome_histograms) {
   // chrome.send() will not work without bindings.
   CHECK(!enable_chrome_send);
   // UntrustedWebUIController should never enable WebUI bindings that expose
diff --git a/chrome/browser/ui/webui/top_chrome/untrusted_top_chrome_web_ui_controller.h b/chrome/browser/ui/webui/top_chrome/untrusted_top_chrome_web_ui_controller.h
index 1c251d6..1a9f45d 100644
--- a/chrome/browser/ui/webui/top_chrome/untrusted_top_chrome_web_ui_controller.h
+++ b/chrome/browser/ui/webui/top_chrome/untrusted_top_chrome_web_ui_controller.h
@@ -18,8 +18,10 @@
 // interface needed.
 class UntrustedTopChromeWebUIController : public TopChromeWebUIController {
  public:
-  explicit UntrustedTopChromeWebUIController(content::WebUI* contents,
-                                             bool enable_chrome_send = false);
+  explicit UntrustedTopChromeWebUIController(
+      content::WebUI* contents,
+      bool enable_chrome_send = false,
+      bool enable_chrome_histograms = false);
   ~UntrustedTopChromeWebUIController() override;
   UntrustedTopChromeWebUIController(UntrustedTopChromeWebUIController&) =
       delete;
diff --git a/chrome/browser/ui/webui/top_chrome/webui_contents_preload_manager_unittest.cc b/chrome/browser/ui/webui/top_chrome/webui_contents_preload_manager_unittest.cc
index 18944104..9c46b0a 100644
--- a/chrome/browser/ui/webui/top_chrome/webui_contents_preload_manager_unittest.cc
+++ b/chrome/browser/ui/webui/top_chrome/webui_contents_preload_manager_unittest.cc
@@ -21,7 +21,6 @@
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/memory_pressure/fake_memory_pressure_monitor.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/web_contents_tester.h"
@@ -93,10 +92,6 @@
     return WebUIContentsPreloadManager::GetInstance();
   }
 
-  void SetMemoryPressureLevel(base::MemoryPressureLevel level) {
-    fake_memory_monitor_.SetAndNotifyMemoryPressure(level);
-  }
-
   MockPreloadCandidateSelector& preload_candidate_selector() {
     return *preload_candidate_selector_;
   }
@@ -105,7 +100,6 @@
 
  private:
   base::MemoryPressureListenerRegistry memory_pressure_listener_registry_;
-  memory_pressure::test::FakeMemoryPressureMonitor fake_memory_monitor_;
   base::test::ScopedFeatureList enabled_feature_{
       features::kPreloadTopChromeWebUI};
   WebUIContentsPreloadManagerTestAPI test_api_;
@@ -125,7 +119,8 @@
 
 TEST_F(WebUIContentsPreloadManagerTest, NoPreloadUnderHeavyMemoryPressure) {
   // Don't preload if the memory pressure is moderate or higher.
-  SetMemoryPressureLevel(base::MEMORY_PRESSURE_LEVEL_MODERATE);
+  base::MemoryPressureListenerRegistry::SimulatePressureNotification(
+      base::MEMORY_PRESSURE_LEVEL_MODERATE);
   std::unique_ptr<content::BrowserContext> browser_context =
       std::make_unique<TestingProfile>();
   test_api().MaybePreloadForBrowserContext(browser_context.get());
diff --git a/chrome/browser/ui/webui/webui_embedding_context.cc b/chrome/browser/ui/webui/webui_embedding_context.cc
index 76fc4ab..d8fedcb 100644
--- a/chrome/browser/ui/webui/webui_embedding_context.cc
+++ b/chrome/browser/ui/webui/webui_embedding_context.cc
@@ -12,6 +12,7 @@
 namespace webui {
 namespace {
 
+#if !BUILDFLAG(IS_ANDROID)
 // Tracks changes to the wrapped `browser_window_interface_`, notifying clients
 // of changes as approprirate.
 class EmbeddingBrowserTracker {
@@ -60,6 +61,7 @@
   // Notifies clients of changes to `browser_window_interface_`.
   base::RepeatingClosure browser_change_cb_;
 };
+#endif
 
 // Tracks changes to the wrapped `tab_interface_`, notifying clients of changes
 // as approprirate.
@@ -144,6 +146,7 @@
     return EmbedderContextData::FromWebContents(web_contents);
   }
 
+#if !BUILDFLAG(IS_ANDROID)
   void SetBrowserWindowInterface(
       BrowserWindowInterface* browser_window_interface) {
     // Tabs will always belong to a browser and are tracked together, both
@@ -163,12 +166,31 @@
       browser_tracker_.reset();
     }
   }
+#endif
+
+  BrowserWindowInterface* GetBrowserWindowInterface() {
+#if !BUILDFLAG(IS_ANDROID)
+    // Source the browser interface either directly from the tracked browser or
+    // via the tracked tab.
+    if (tab_tracker_) {
+      return tab_tracker_->tab_interface()
+                 ? tab_tracker_->tab_interface()->GetBrowserWindowInterface()
+                 : nullptr;
+    }
+    if (browser_tracker_) {
+      return browser_tracker_->browser_window_interface();
+    }
+#endif
+    return nullptr;
+  }
 
   void SetTabInterface(tabs::TabInterface* tab_interface) {
+#if !BUILDFLAG(IS_ANDROID)
     // Tabs will always belong to a browser and are tracked together, both
     // browser and tab trackers should not be set independently.
     CHECK(!browser_tracker_)
         << "Browser and tab trackers should not be set independently";
+#endif
     if (!tab_tracker_) {
       tab_tracker_ = std::make_unique<EmbeddingTabTracker>(
           base::BindRepeating(&EmbedderContextData::NotifyTabChanged,
@@ -185,20 +207,6 @@
     }
   }
 
-  BrowserWindowInterface* GetBrowserWindowInterface() {
-    // Source the browser interface either directly from the tracked browser or
-    // via the tracked tab.
-    if (tab_tracker_) {
-      return tab_tracker_->tab_interface()
-                 ? tab_tracker_->tab_interface()->GetBrowserWindowInterface()
-                 : nullptr;
-    }
-    if (browser_tracker_) {
-      return browser_tracker_->browser_window_interface();
-    }
-    return nullptr;
-  }
-
   tabs::TabInterface* GetTabInterface() {
     return tab_tracker_ ? tab_tracker_->tab_interface() : nullptr;
   }
@@ -225,8 +233,10 @@
   // Notifies clients their embedding tab has changed.
   void NotifyTabChanged() { tab_change_callbacks_.Notify(); }
 
+#if !BUILDFLAG(IS_ANDROID)
   // Defined only if actively tracking an embedding browser.
   std::unique_ptr<EmbeddingBrowserTracker> browser_tracker_;
+#endif
 
   // Defined only if actively tracking an embedding tab.
   std::unique_ptr<EmbeddingTabTracker> tab_tracker_;
@@ -258,18 +268,14 @@
       }));
 }
 
+#if !BUILDFLAG(IS_ANDROID)
 void SetBrowserWindowInterface(
     content::WebContents* host_contents,
     BrowserWindowInterface* browser_window_interface) {
   EmbedderContextData::GetOrCreate(host_contents)
       ->SetBrowserWindowInterface(browser_window_interface);
 }
-
-void SetTabInterface(content::WebContents* host_contents,
-                     tabs::TabInterface* tab_interface) {
-  EmbedderContextData::GetOrCreate(host_contents)
-      ->SetTabInterface(tab_interface);
-}
+#endif
 
 BrowserWindowInterface* GetBrowserWindowInterface(
     content::WebContents* host_contents) {
@@ -277,6 +283,12 @@
       ->GetBrowserWindowInterface();
 }
 
+void SetTabInterface(content::WebContents* host_contents,
+                     tabs::TabInterface* tab_interface) {
+  EmbedderContextData::GetOrCreate(host_contents)
+      ->SetTabInterface(tab_interface);
+}
+
 tabs::TabInterface* GetTabInterface(content::WebContents* host_contents) {
   return EmbedderContextData::GetOrCreate(host_contents)->GetTabInterface();
 }
diff --git a/chrome/browser/ui/webui/webui_embedding_context.h b/chrome/browser/ui/webui/webui_embedding_context.h
index ee85968..ca0e4e1 100644
--- a/chrome/browser/ui/webui/webui_embedding_context.h
+++ b/chrome/browser/ui/webui/webui_embedding_context.h
@@ -30,10 +30,17 @@
 base::CallbackListSubscription InitEmbeddingContext(
     tabs::TabInterface* tab_interface);
 
+#if !BUILDFLAG(IS_ANDROID)
 // Called by embedders to set the browser for `host_contents`.
 void SetBrowserWindowInterface(
     content::WebContents* host_contents,
     BrowserWindowInterface* browser_window_interface);
+#endif
+
+// Gets the interface for the embedding browser. Clients should not persist this
+// reference. May be null.
+BrowserWindowInterface* GetBrowserWindowInterface(
+    content::WebContents* host_contents);
 
 // Called by embedders to set the tab interface for `host_contents`. A tab is
 // implicitly hosted in a browser and this setter also configures tracking of
@@ -41,11 +48,6 @@
 void SetTabInterface(content::WebContents* host_contents,
                      tabs::TabInterface* tab_interface);
 
-// Gets the interface for the embedding browser. Clients should not persist this
-// reference. May be null.
-BrowserWindowInterface* GetBrowserWindowInterface(
-    content::WebContents* host_contents);
-
 // Gets the interface for the embedding tab. Clients should not persist this
 // reference. May be null.
 tabs::TabInterface* GetTabInterface(content::WebContents* host_contents);
diff --git a/chrome/browser/ui/webui/webui_urls_for_test.h b/chrome/browser/ui/webui/webui_urls_for_test.h
index 0214514..4dfada1 100644
--- a/chrome/browser/ui/webui/webui_urls_for_test.h
+++ b/chrome/browser/ui/webui/webui_urls_for_test.h
@@ -287,6 +287,7 @@
     "chrome://discards",
     "chrome://glic",
     "chrome://glic-fre",
+    "chrome-untrusted://glic",
     "chrome://history-sync-optin",
     // Not a valid URL; only internals/session-service is valid.
     "chrome://internals",
diff --git a/chrome/browser/ui/webui_browser/webui_browser_ui.cc b/chrome/browser/ui/webui_browser/webui_browser_ui.cc
index dc20d795..9ad6ea8 100644
--- a/chrome/browser/ui/webui_browser/webui_browser_ui.cc
+++ b/chrome/browser/ui/webui_browser/webui_browser_ui.cc
@@ -90,7 +90,9 @@
 // enable_chrome_send to MojoWebUIController constructor, since they're
 // a package deal via BindingsPolicyValue::kWebUi.
 WebUIBrowserUI::WebUIBrowserUI(content::WebUI* web_ui)
-    : ui::MojoWebUIController(web_ui, /*enable_chrome_send=*/true) {
+    : ui::MojoWebUIController(web_ui,
+                              /*enable_chrome_send=*/true,
+                              /*enable_chrome_histograms=*/true) {
   WebUIBrowserWindow* webui_browser_window =
       WebUIBrowserWindow::FromWebShellWebContents(web_ui->GetWebContents());
   browser_ = webui_browser_window->browser();
diff --git a/chrome/browser/web_applications/commands/apply_manifest_migration_command.cc b/chrome/browser/web_applications/commands/apply_manifest_migration_command.cc
index cfdbe7b..e977ba25 100644
--- a/chrome/browser/web_applications/commands/apply_manifest_migration_command.cc
+++ b/chrome/browser/web_applications/commands/apply_manifest_migration_command.cc
@@ -213,6 +213,10 @@
 void ApplyManifestMigrationCommand::OnIconsCopied(bool success) {
   GetMutableDebugValue().Set("icon_copy_successful_for_forced_migration",
                              success);
+
+  all_apps_lock_->install_manager().NotifyWebAppManifestUpdated(
+      destination_app_id_);
+
   if (!success) {
     CompleteCommandAndSelfDestruct(
         ApplyManifestMigrationResult::kAppMigrationFailedDuringIconCopy);
diff --git a/chrome/browser/web_applications/commands/fetch_manifest_and_update_command_browsertest.cc b/chrome/browser/web_applications/commands/fetch_manifest_and_update_command_browsertest.cc
index 89c151d..8b6b689 100644
--- a/chrome/browser/web_applications/commands/fetch_manifest_and_update_command_browsertest.cc
+++ b/chrome/browser/web_applications/commands/fetch_manifest_and_update_command_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_future.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
 #include "chrome/browser/ui/web_applications/web_app_browsertest_base.h"
 #include "chrome/browser/web_applications/commands/fetch_manifest_and_update_result.h"
@@ -71,70 +72,19 @@
                                    {});
   }
 
-  void SetUp() override {
-    embedded_https_test_server().RegisterRequestHandler(base::BindRepeating(
-        &FetchManifestAndUpdateCommandMigrationTest::HandleRequest,
-        base::Unretained(this)));
-    FetchManifestAndUpdateCommandTest::SetUp();
-  }
-
-  void SetRequestOverride(
-      base::RepeatingCallback<std::unique_ptr<net::test_server::HttpResponse>(
-          const net::test_server::HttpRequest& request)> handler) {
-    request_override_ = std::move(handler);
-  }
-
  private:
-  std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
-      const net::test_server::HttpRequest& request) {
-    if (request_override_) {
-      return request_override_.Run(request);
-    }
-    return nullptr;
-  }
-
-  base::RepeatingCallback<std::unique_ptr<net::test_server::HttpResponse>(
-      const net::test_server::HttpRequest& request)>
-      request_override_;
   base::test::ScopedFeatureList feature_list_;
 };
 
 IN_PROC_BROWSER_TEST_F(FetchManifestAndUpdateCommandMigrationTest,
                        CheckMigrateFromTriggersUpdate) {
-  webapps::AppId app_a_id = InstallWebAppFromPageAndCloseAppBrowser(
-      browser(), embedded_https_test_server().GetURL("/web_apps/basic.html"));
-  webapps::ManifestId app_a_manifest_id =
-      provider().registrar_unsafe().GetAppManifestId(app_a_id);
+  Browser* app_browser = InstallWebAppFromPageGetBrowser(
+      browser(), embedded_https_test_server().GetURL(
+                     "/web_apps/migration/migrate_from/suggest.html"));
+  webapps::AppId app_a_id = AppBrowserController::From(app_browser)->app_id();
 
-  Browser* app_browser = LaunchWebAppBrowser(app_a_id);
-
-  GURL app_b_manifest_url =
-      embedded_https_test_server().GetURL("/banners/manifest_b.json");
   GURL app_b_url = embedded_https_test_server().GetURL(
-      "/banners/manifest_test_page.html?manifest=manifest_b.json");
-
-  std::string manifest_b_content = R"(
-        {
-          "name": "App B",
-          "start_url": "manifest_test_page.html",
-          "display": "standalone",
-          "migrate_from": [{ "id": "/web_apps/basic.html",
-                             "install_url": "/web_apps/basic.html" }]
-        }
-      )";
-
-  SetRequestOverride(base::BindLambdaForTesting(
-      [&](const net::test_server::HttpRequest& request)
-          -> std::unique_ptr<net::test_server::HttpResponse> {
-        if (request.GetURL() == app_b_manifest_url) {
-          auto http_response =
-              std::make_unique<net::test_server::BasicHttpResponse>();
-          http_response->set_code(net::HTTP_OK);
-          http_response->set_content(manifest_b_content);
-          return http_response;
-        }
-        return nullptr;
-      }));
+      "/web_apps/migration/migrate_to/update_trigger_no_update.html");
 
   base::HistogramTester histogram_tester;
 
@@ -159,41 +109,13 @@
 
 IN_PROC_BROWSER_TEST_F(FetchManifestAndUpdateCommandMigrationTest,
                        CheckMigrateFromTriggersUpdate_WithUpdate) {
-  webapps::AppId app_a_id = InstallWebAppFromPageAndCloseAppBrowser(
-      browser(), embedded_https_test_server().GetURL("/web_apps/basic.html"));
-  webapps::ManifestId app_a_manifest_id =
-      provider().registrar_unsafe().GetAppManifestId(app_a_id);
+  Browser* app_browser = InstallWebAppFromPageGetBrowser(
+      browser(), embedded_https_test_server().GetURL(
+                     "/web_apps/migration/migrate_from/suggest.html"));
+  webapps::AppId app_a_id = AppBrowserController::From(app_browser)->app_id();
 
-  Browser* app_browser = LaunchWebAppBrowser(app_a_id);
-
-  GURL app_b_manifest_url =
-      embedded_https_test_server().GetURL("/banners/manifest_b.json");
   GURL app_b_url = embedded_https_test_server().GetURL(
-      "/banners/manifest_test_page.html?manifest=manifest_b.json");
-
-  std::string manifest_b_content = R"(
-        {
-          "name": "App B",
-          "start_url": "manifest_test_page.html",
-          "display": "standalone",
-          "migrate_from": [{ "id": "/web_apps/basic.html",
-                             "install_url":
-                                 "/web_apps/get_manifest.html?basic_new_name.json" }]
-        }
-      )";
-
-  SetRequestOverride(base::BindLambdaForTesting(
-      [&](const net::test_server::HttpRequest& request)
-          -> std::unique_ptr<net::test_server::HttpResponse> {
-        if (request.GetURL() == app_b_manifest_url) {
-          auto http_response =
-              std::make_unique<net::test_server::BasicHttpResponse>();
-          http_response->set_code(net::HTTP_OK);
-          http_response->set_content(manifest_b_content);
-          return http_response;
-        }
-        return nullptr;
-      }));
+      "/web_apps/migration/migrate_to/update_trigger_with_update.html");
 
   base::HistogramTester histogram_tester;
 
@@ -213,11 +135,11 @@
   histogram_tester.ExpectBucketCount("WebApp.FetchManifestAndUpdate.Result",
                                      FetchManifestAndUpdateResult::kSuccess, 1);
 
-  EXPECT_EQ("Basic web app",
+  EXPECT_EQ("Migrate From",
             provider().registrar_unsafe().GetAppShortName(app_a_id));
   const WebApp* app_a = provider().registrar_unsafe().GetAppById(app_a_id);
   ASSERT_TRUE(app_a->pending_update_info().has_value());
-  EXPECT_EQ(app_a->pending_update_info()->name(), "Basic web app 2");
+  EXPECT_EQ(app_a->pending_update_info()->name(), "Migrate From Updated Name");
 }
 
 }  // namespace web_app
diff --git a/chrome/build/android-desktop-x64.pgo.txt b/chrome/build/android-desktop-x64.pgo.txt
index 73a2e08..55effe1e 100644
--- a/chrome/build/android-desktop-x64.pgo.txt
+++ b/chrome/build/android-desktop-x64.pgo.txt
@@ -1 +1 @@
-chrome-android-desktop-x64-main-1772020375-bcabeafc98465af4bcbd37bdf6e612662a9dd0a8-62c21f198c8073ed533e4d1319ac14f53e323ba9.profdata
+chrome-android-desktop-x64-main-1772042384-c0c2c7512017f161bf2d44bbce1b69b290bec6bc-10cb2f61ce3a19dd622781b7ef7453dbd7f7c601.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 6ed4ac47..0945d7d 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1772035142-c62f226053ca8fd7a7ce5fa687de32e0efec5f9c-c8643fe73853e33b640acdc7d01567b7dc67f679.profdata
+chrome-mac-arm-main-1772056711-827e4e9e4c3d7ada4679f367203036451a39e7b5-b3c06f3dbeabd32387b95f309f63a3a6023cd029.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index a6b62626..7936acf 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1772020375-9e69d75fbc48a3a6ddcb708a87d7d34a894af516-62c21f198c8073ed533e4d1319ac14f53e323ba9.profdata
+chrome-mac-main-1772042384-2697c9b3f0e8336776b8fd7e2b3962f04e1913a7-10cb2f61ce3a19dd622781b7ef7453dbd7f7c601.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index 2c3198c5..d1f9667 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1772020375-dcc6474afc66aedc6246ef6bbb9901dcb46da7a1-62c21f198c8073ed533e4d1319ac14f53e323ba9.profdata
+chrome-win-arm64-main-1772042384-dec06a1b559cf4365788f7d3f78a1ce0ea873410-10cb2f61ce3a19dd622781b7ef7453dbd7f7c601.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 96c4f55..de81be4 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1772020375-040df2882c348194175bcf3ec6afa5f257a0c683-62c21f198c8073ed533e4d1319ac14f53e323ba9.profdata
+chrome-win32-main-1772042384-65321eb690f819aca9c1354d41aff4300f9ea974-10cb2f61ce3a19dd622781b7ef7453dbd7f7c601.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 6d119169..0723fb73 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1772020375-8d3d2fe65fc6488e40e5dfc30cde787a592d9c2b-62c21f198c8073ed533e4d1319ac14f53e323ba9.profdata
+chrome-win64-main-1772042384-13bc96fa6c7dc3e3d662df54b7eca084b9ba6377-10cb2f61ce3a19dd622781b7ef7453dbd7f7c601.profdata
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index c64007c8..0f4f229 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -731,14 +731,6 @@
 
   enabled_features = []
 
-  if (enable_glic) {
-    enabled_features += [ "enable_glic" ]
-  }
-
-  if (enable_glic) {
-    enabled_features += [ "enable_glic" ]
-  }
-
   if (skip_android_unmigrated_actor_files) {
     enabled_features += [ "skip_android_unmigrated_actor_files" ]
   }
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index e7e9f86..0de8f85 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -905,6 +905,8 @@
 BASE_FEATURE(kGlicRecordMemoryFootprintMetrics,
              base::FEATURE_ENABLED_BY_DEFAULT);
 
+BASE_FEATURE(kGlicRegionSelectionNew, base::FEATURE_DISABLED_BY_DEFAULT);
+
 BASE_FEATURE(kGlicWebClientUnresponsiveMetrics,
              base::FEATURE_ENABLED_BY_DEFAULT);
 
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 0d10e63b..37e593f 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -616,6 +616,9 @@
 BASE_DECLARE_FEATURE(kGlicRecordMemoryFootprintMetrics);
 
 COMPONENT_EXPORT(CHROME_FEATURES)
+BASE_DECLARE_FEATURE(kGlicRegionSelectionNew);
+
+COMPONENT_EXPORT(CHROME_FEATURES)
 BASE_DECLARE_FEATURE(kGlicWebClientUnresponsiveMetrics);
 
 COMPONENT_EXPORT(CHROME_FEATURES)
diff --git a/chrome/common/extensions/api/tabs.json b/chrome/common/extensions/api/tabs.json
index cb2b08e..77010d2 100644
--- a/chrome/common/extensions/api/tabs.json
+++ b/chrome/common/extensions/api/tabs.json
@@ -270,7 +270,7 @@
         "name": "sendMessage",
         "nocompile": true,
         "type": "function",
-        "description": "Sends a single message to the content script(s) in the specified tab, with an optional callback to run when a response is sent back.  The $(ref:runtime.onMessage) event is fired in each content script running in the specified tab for the current extension.",
+        "description": "Sends a single message to the content script(s) in the specified tab. The $(ref:runtime.onMessage) event is fired in each content script running in the specified tab for the current extension.",
         "parameters": [
           {
             "type": "integer",
@@ -304,11 +304,12 @@
         "returns_async": {
           "name": "callback",
           "optional": true,
+          "description": "Promise that resolves with the response from the content script. If an error occurs while connecting to the specified tab, the promise will be rejected.",
           "parameters": [
             {
               "name": "response",
               "type": "any",
-              "description": "The JSON response object sent by the handler of the message. If an error occurs while connecting to the specified tab, the promise will be rejected."
+              "description": "The JSON response object sent by the handler of the message."
             }
           ]
         }
diff --git a/chrome/common/features.gni b/chrome/common/features.gni
index a9baa1c..de0bafb3 100644
--- a/chrome/common/features.gni
+++ b/chrome/common/features.gni
@@ -46,7 +46,9 @@
   enable_chrome_notifications = is_mac || is_win || is_linux
 
   # Enables inclusion of glic in the build.
-  enable_glic = is_mac || is_win || is_linux || is_chromeos || is_android
+  # NOTE: This flag is currently being removed and shouldn't be used in new
+  # code (See crbug.com/486982086).
+  enable_glic = true
 
   # Skips unmigrated actor files in the build on Android. This is temporary, and
   # will eventually be removed once migration is done. Adding this flag likely
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index 36db730..ad4612a 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -157,6 +157,10 @@
 inline constexpr char kChromeUIGlicURL[] = "chrome://glic/";
 inline constexpr char kChromeUIGlicFreHost[] = "glic-fre";
 inline constexpr char kChromeUIGlicFreURL[] = "chrome://glic-fre";
+inline constexpr char kChromeUIGlicUntrustedHost[] = "glic";
+inline constexpr char kChromeUIGlicUntrustedURL[] = "chrome-untrusted://glic/";
+inline constexpr char kChromeUIGlicSelectionOverlayURL[] =
+    "chrome-untrusted://glic/selection-overlay/";
 inline constexpr char kChromeUIContextualTasksVirtualHost[] = "googlesearch";
 inline constexpr char kChromeUIContextualTasksVirtualURL[] =
     "chrome://googlesearch";
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_app_controller.cc b/chrome/renderer/accessibility/read_anything/read_anything_app_controller.cc
index 54d94ad..c8f2e3b 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_app_controller.cc
+++ b/chrome/renderer/accessibility/read_anything/read_anything_app_controller.cc
@@ -573,7 +573,7 @@
 }
 
 void ReadAnythingAppController::ProcessPendingUpdatesIfAllowed() {
-  if (IsUpdateProcessingPaused()) {
+  if (IsUpdateProcessingPaused() || !model_.ContainsActiveTree()) {
     return;
   }
 
@@ -2851,10 +2851,10 @@
     model_.set_next_distillation_method(
         ReadAnythingAppModel::DistillationMethod::kScreen2x);
 
-    // Only update distillation required if we have an active tree, otherwise
-    // wait for event to distill.
+    // Only attempt distillation if we have an active tree, otherwise only
+    // update the model and wait for event to distill.
+    model_.set_requires_distillation(true);
     if (model_.ContainsActiveTree()) {
-      model_.set_requires_distillation(true);
       DistillNewTree();
     }
     return;
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_app_controller_browsertest.cc b/chrome/renderer/accessibility/read_anything/read_anything_app_controller_browsertest.cc
index 871ff89..d708932b 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_app_controller_browsertest.cc
+++ b/chrome/renderer/accessibility/read_anything/read_anything_app_controller_browsertest.cc
@@ -3214,6 +3214,35 @@
                                   base::Seconds(1));
 }
 
+TEST_F(ReadAnythingAppControllerTest,
+       ProcessPendingUpdatesIfAllowed_ExitsIfNoTree) {
+  // Destroy existing tree created in Setup().
+  controller().OnAXTreeDestroyed(tree_id_);
+  ASSERT_FALSE(model().ContainsActiveTree());
+
+  model().set_reset_draw_timer(true);
+  model().set_requires_distillation(false);
+
+  controller().ProcessPendingUpdatesIfAllowed();
+
+  // Value for reset_draw_timer didn't change because of early return.
+  EXPECT_TRUE(model().reset_draw_timer());
+}
+
+TEST_F(ReadAnythingAppControllerTest,
+       ProcessPendingUpdatesIfAllowed_ExecutesIfTree) {
+  // There's already an Active tree from Setup() so we don't need to create it.
+  ASSERT_TRUE(model().ContainsActiveTree());
+
+  model().set_reset_draw_timer(true);
+  model().set_requires_distillation(false);
+
+  controller().ProcessPendingUpdatesIfAllowed();
+
+  // Value for reset_draw_timer changed because updates were processed.
+  EXPECT_FALSE(model().reset_draw_timer());
+}
+
 class ReadAnythingAppControllerImmersiveTest
     : public ReadAnythingAppControllerTest {
  public:
@@ -4958,6 +4987,35 @@
 }
 
 TEST_F(ReadAnythingAppControllerReadabilityTest,
+       UpdateContent_EmptyContentNoTree_SkipsDistillationAttempt) {
+  Mock::VerifyAndClearExpectations(distiller_);
+
+  // Destroy existing tree created in Setup().
+  controller().OnAXTreeDestroyed(tree_id_);
+
+  ASSERT_FALSE(model().ContainsActiveTree());
+
+  EXPECT_CALL(*distiller_, Distill).Times(0);
+  controller().UpdateContent("", "");
+
+  EXPECT_TRUE(model().requires_distillation());
+}
+
+TEST_F(ReadAnythingAppControllerReadabilityTest,
+       UpdateContent_EmptyContentWithTree_DoesDistillationAttempt) {
+  Mock::VerifyAndClearExpectations(distiller_);
+
+  // There's already an Active tree from Setup() so we don't need to create it.
+  ASSERT_TRUE(model().ContainsActiveTree());
+
+  EXPECT_CALL(*distiller_, Distill).Times(1);
+
+  controller().UpdateContent("", "");
+
+  EXPECT_FALSE(model().requires_distillation());
+}
+
+TEST_F(ReadAnythingAppControllerReadabilityTest,
        OnActiveAXTreeIDChanged_ResetsDistillationMethod) {
   // Simulate a failure on the first page switching to Screen2x.
   model().set_current_content_distillation_method(
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_app_model.cc b/chrome/renderer/accessibility/read_anything/read_anything_app_model.cc
index 79b1da3..f53d2ba 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_app_model.cc
+++ b/chrome/renderer/accessibility/read_anything/read_anything_app_model.cc
@@ -1095,8 +1095,10 @@
       case ui::AXEventGenerator::Event::FOCUS_CHANGED:
       case ui::AXEventGenerator::Event::FLOW_FROM_CHANGED:
       case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
+      case ui::AXEventGenerator::Event::GRAMMAR_MARKER_CHANGED:
       case ui::AXEventGenerator::Event::HASPOPUP_CHANGED:
       case ui::AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
+      case ui::AXEventGenerator::Event::HIGHLIGHT_MARKER_CHANGED:
       case ui::AXEventGenerator::Event::IGNORED_CHANGED:
       case ui::AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED:
       case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
@@ -1135,6 +1137,7 @@
       case ui::AXEventGenerator::Event::SELECTED_VALUE_CHANGED:
       case ui::AXEventGenerator::Event::SET_SIZE_CHANGED:
       case ui::AXEventGenerator::Event::SORT_CHANGED:
+      case ui::AXEventGenerator::Event::SPELLING_MARKER_CHANGED:
       case ui::AXEventGenerator::Event::STATE_CHANGED:
       case ui::AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
       case ui::AXEventGenerator::Event::TEXT_SELECTION_CHANGED:
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_node_utils.cc b/chrome/renderer/accessibility/read_anything/read_anything_node_utils.cc
index 37ca500..8161ad9 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_node_utils.cc
+++ b/chrome/renderer/accessibility/read_anything/read_anything_node_utils.cc
@@ -110,6 +110,10 @@
                              const std::string& html_tag) {
   ax::mojom::Role role = ax_node->GetRole();
 
+  if (ui::IsTextField(ax_node->GetRole())) {
+    return "div";
+  }
+
   // Some nodes in PDFs don't have an HTML tag so use role instead.
   switch (role) {
     case ax::mojom::Role::kEmbeddedObject:
diff --git a/chrome/renderer/accessibility/read_anything/read_anything_node_utils_unittest.cc b/chrome/renderer/accessibility/read_anything/read_anything_node_utils_unittest.cc
index 015c6397..d7f9f16 100644
--- a/chrome/renderer/accessibility/read_anything/read_anything_node_utils_unittest.cc
+++ b/chrome/renderer/accessibility/read_anything/read_anything_node_utils_unittest.cc
@@ -465,6 +465,16 @@
   EXPECT_EQ(a11y::GetHtmlTagForPDF(&node, "p"), "span");
 }
 
+TEST_F(ReadAnythingNodeUtilsTest, GetHtmlTagForPdf_ReturnsDivForTextField) {
+  ui::AXNodeData data;
+  data.id = 2;
+  data.role = ax::mojom::Role::kTextField;
+  ui::AXTree tree;
+  ui::AXNode node(&tree, nullptr, 2, 0);
+  node.SetData(std::move(data));
+  EXPECT_EQ(a11y::GetHtmlTagForPDF(&node, ""), "div");
+}
+
 TEST_F(ReadAnythingNodeUtilsTest, GetHtmlTagForPdf_LinkTagReturned) {
   ui::AXNodeData data = test::TextNode(2);
   data.role = ax::mojom::Role::kLink;
diff --git a/chrome/services/file_util/obfuscated_archive_analysis_delegate.h b/chrome/services/file_util/obfuscated_archive_analysis_delegate.h
index 3410e6ad..2cbaaea 100644
--- a/chrome/services/file_util/obfuscated_archive_analysis_delegate.h
+++ b/chrome/services/file_util/obfuscated_archive_analysis_delegate.h
@@ -7,7 +7,10 @@
 
 #include "chrome/utility/safe_browsing/archive_analysis_delegate.h"
 #include "components/enterprise/obfuscation/core/utils.h"
+
+#if USE_UNRAR
 #include "third_party/unrar/google/unrar_wrapper.h"
+#endif
 
 namespace safe_browsing {
 
diff --git a/chrome/services/file_util/regular_archive_analysis_delegate.cc b/chrome/services/file_util/regular_archive_analysis_delegate.cc
index 27fd89bf..16d93e79 100644
--- a/chrome/services/file_util/regular_archive_analysis_delegate.cc
+++ b/chrome/services/file_util/regular_archive_analysis_delegate.cc
@@ -9,9 +9,12 @@
 #include "base/containers/span.h"
 #include "base/files/file.h"
 #include "chrome/utility/safe_browsing/zip_writer_delegate.h"
+#include "third_party/zlib/google/zip_reader.h"
+
+#if USE_UNRAR
 #include "third_party/unrar/google/unrar_delegates.h"
 #include "third_party/unrar/google/unrar_wrapper.h"
-#include "third_party/zlib/google/zip_reader.h"
+#endif
 
 namespace safe_browsing {
 
diff --git a/chrome/services/file_util/regular_archive_analysis_delegate.h b/chrome/services/file_util/regular_archive_analysis_delegate.h
index 977d025..5716fe9 100644
--- a/chrome/services/file_util/regular_archive_analysis_delegate.h
+++ b/chrome/services/file_util/regular_archive_analysis_delegate.h
@@ -6,7 +6,10 @@
 #define CHROME_SERVICES_FILE_UTIL_REGULAR_ARCHIVE_ANALYSIS_DELEGATE_H_
 
 #include "chrome/utility/safe_browsing/archive_analysis_delegate.h"
+
+#if USE_UNRAR
 #include "third_party/unrar/google/unrar_delegates.h"
+#endif
 
 namespace safe_browsing {
 
diff --git a/chrome/services/sharing/nearby/platform.cc b/chrome/services/sharing/nearby/platform.cc
index c37aa24..ecb6527c 100644
--- a/chrome/services/sharing/nearby/platform.cc
+++ b/chrome/services/sharing/nearby/platform.cc
@@ -384,7 +384,7 @@
 
   const mojo::SharedRemote<::sharing::mojom::MdnsManager>& mdns_manager =
       nearby_shared_remotes->mdns_manager;
-  if (features::IsNearbyMdnsEnabled() && !mdns_manager.is_bound()) {
+  if (!mdns_manager.is_bound()) {
     LOG(ERROR) << "MdnsManager not bound. Returning null WifiLan medium";
     return nullptr;
   }
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_medium.cc b/chrome/services/sharing/nearby/platform/wifi_lan_medium.cc
index d2d51c2..16a8ab08 100644
--- a/chrome/services/sharing/nearby/platform/wifi_lan_medium.cc
+++ b/chrome/services/sharing/nearby/platform/wifi_lan_medium.cc
@@ -115,7 +115,7 @@
   // NOTE: We do not set the disconnect handler for the SharedRemotes here. They
   // are fundamental dependencies of the Nearby Connections process, which will
   // crash if any dependency disconnects.
-  if (mdns_manager_.is_bound() && ::features::IsNearbyMdnsEnabled()) {
+  if (mdns_manager_.is_bound()) {
     mdns_manager_->AddObserver(mdns_observer_.BindNewPipeAndPassRemote());
     VLOG(1) << " Added Mdns observer.";
   }
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_medium_unittest.cc b/chrome/services/sharing/nearby/platform/wifi_lan_medium_unittest.cc
index 742f38e..d6beb166 100644
--- a/chrome/services/sharing/nearby/platform/wifi_lan_medium_unittest.cc
+++ b/chrome/services/sharing/nearby/platform/wifi_lan_medium_unittest.cc
@@ -9,7 +9,6 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/task/thread_pool.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
@@ -28,7 +27,6 @@
 #include "chromeos/ash/services/network_config/in_process_instance.h"
 #include "chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
-#include "components/cross_device/nearby/nearby_features.h"
 #include "components/onc/onc_constants.h"
 #include "components/onc/onc_pref_names.h"
 #include "components/prefs/testing_pref_service.h"
@@ -694,12 +692,7 @@
 /*============================================================================*/
 // Begin: StartDiscovery()
 /*============================================================================*/
-TEST_F(WifiLanMediumTest, Discovery_FlagEnabled_StartAndStopSucceeds) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitWithFeatures(
-      /*enabled_features=*/{::features::kEnableNearbyMdns},
-      /*disabled_features=*/{});
-
+TEST_F(WifiLanMediumTest, Discovery_StartAndStopSucceeds) {
   Initialize(WifiInitState::kComplete);
 
   api::WifiLanMedium::DiscoveredServiceCallback discovery_callback = {
@@ -713,31 +706,7 @@
       /*service_type=*/kNearbyServiceType));
 }
 
-TEST_F(WifiLanMediumTest, Discovery_FlagDisabled_StartAndStopFails) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitWithFeatures(
-      /*enabled_features=*/{},
-      /*disabled_features=*/{::features::kEnableNearbyMdns});
-
-  Initialize(WifiInitState::kComplete);
-
-  api::WifiLanMedium::DiscoveredServiceCallback discovery_callback = {
-      .service_discovered_cb = [](const NsdServiceInfo& service_info) {},
-      .service_lost_cb = [](const NsdServiceInfo& service_info) {}};
-
-  EXPECT_FALSE(wifi_lan_medium_->StartDiscovery(
-      /*service_type=*/kNearbyServiceType,
-      /*callback=*/std::move(discovery_callback)));
-  EXPECT_FALSE(wifi_lan_medium_->StopDiscovery(
-      /*service_type=*/kNearbyServiceType));
-}
-
 TEST_F(WifiLanMediumTest, Discovery_StopUnknownServiceFails) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitWithFeatures(
-      /*enabled_features=*/{::features::kEnableNearbyMdns},
-      /*disabled_features=*/{});
-
   Initialize(WifiInitState::kComplete);
 
   api::WifiLanMedium::DiscoveredServiceCallback discovery_callback = {
@@ -752,11 +721,6 @@
 }
 
 TEST_F(WifiLanMediumTest, Discovery_FindsService) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitWithFeatures(
-      /*enabled_features=*/{::features::kEnableNearbyMdns},
-      /*disabled_features=*/{});
-
   Initialize(WifiInitState::kComplete);
 
   StartMdnsDiscovery(/*service_type=*/kNearbyServiceType);
@@ -781,11 +745,6 @@
 }
 
 TEST_F(WifiLanMediumTest, Discovery_LosesAndFindsService) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitWithFeatures(
-      /*enabled_features=*/{::features::kEnableNearbyMdns},
-      /*disabled_features=*/{});
-
   Initialize(WifiInitState::kComplete);
 
   StartMdnsDiscovery(/*service_type=*/kNearbyServiceType);
@@ -830,11 +789,6 @@
 }
 
 TEST_F(WifiLanMediumTest, Discovery_MultipleDiscovery) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitWithFeatures(
-      /*enabled_features=*/{::features::kEnableNearbyMdns},
-      /*disabled_features=*/{});
-
   Initialize(WifiInitState::kComplete);
 
   // Start 2 discovery sessions.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 08e2b5d..813e9b8f 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2624,6 +2624,8 @@
       "//chrome/browser/plus_addresses:browser_tests",
       "//chrome/browser/policy:browser_tests",
       "//chrome/browser/policy:test_support",
+      "//chrome/browser/predictors:browser_tests",
+      "//chrome/browser/predictors:test_support",
       "//chrome/browser/prefs",
       "//chrome/browser/prefs:browser_tests",
       "//chrome/browser/prefs:util",
@@ -3691,7 +3693,6 @@
       "../browser/policy/test/sharing_policy_browsertest.cc",
       "../browser/policy/test/url_blocklist_policy_browsertest.cc",
       "../browser/policy/test/v8_optimizer_policy_browsertest.cc",
-      "../browser/predictors/loading_predictor_browsertest.cc",
       "../browser/prefetch/prefetch_browsertest.cc",
       "../browser/prefs/tracked/pref_hash_browsertest.cc",
       "../browser/preloading/new_tab_page_preload/new_tab_page_preload_browsertest.cc",
@@ -5378,6 +5379,7 @@
         "../browser/ui/views/tabs/tab_group_editor_bubble_view_browsertest.cc",
         "../browser/ui/views/translate/translate_bubble_test_utils_views.cc",
         "../browser/ui/views/translate/translate_bubble_view_browsertest.cc",
+        "../browser/ui/views/ui_devtools_browsertest.cc",
         "../browser/ui/views/upgrade_notification_controller_browsertest.cc",
         "../browser/ui/views/user_education/help_bubble_factory_views_browsertest.cc",
         "../browser/ui/views/web_apps/web_app_uninstall_dialog_browsertest.cc",
@@ -5489,6 +5491,8 @@
         "//components/safe_browsing/core/browser/realtime:test_support",
         "//components/send_tab_to_self",
         "//components/send_tab_to_self:test_support",
+        "//components/ui_devtools",
+        "//components/ui_devtools/views",
         "//components/user_education/views",
         "//services/preferences/tracked",
         "//ui/base/dragdrop:types",
@@ -6772,19 +6776,6 @@
     "../browser/policy/profile_policy_connector_unittest.cc",
     "../browser/policy/serial_allow_usb_devices_for_urls_policy_handler_unittest.cc",
     "../browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc",
-    "../browser/predictors/autocomplete_action_predictor_table_unittest.cc",
-    "../browser/predictors/autocomplete_action_predictor_unittest.cc",
-    "../browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util_unittest.cc",
-    "../browser/predictors/lcp_critical_path_predictor/prewarm_http_disk_cache_manager_unittest.cc",
-    "../browser/predictors/loading_data_collector_unittest.cc",
-    "../browser/predictors/loading_predictor_config_unittest.cc",
-    "../browser/predictors/loading_predictor_tab_helper_unittest.cc",
-    "../browser/predictors/loading_predictor_unittest.cc",
-    "../browser/predictors/loading_stats_collector_unittest.cc",
-    "../browser/predictors/perform_network_context_prefetch_unittest.cc",
-    "../browser/predictors/prefetch_manager_unittest.cc",
-    "../browser/predictors/resource_prefetch_predictor_tables_unittest.cc",
-    "../browser/predictors/resource_prefetch_predictor_unittest.cc",
     "../browser/preloading/prefetch/search_prefetch/field_trial_settings_unittest.cc",
     "../browser/preloading/prefetch/search_prefetch/search_prefetch_keep_alive_request_track_unittest.cc",
     "../browser/profiles/chrome_incognito_mode_policy_handler_unittest.cc",
@@ -7744,10 +7735,6 @@
       "../browser/device_reauth/win/device_authenticator_win_unittest.cc",
       "../browser/enterprise/platform_auth/cloud_ap_provider_win_unittest.cc",
       "../browser/enterprise/platform_auth/cloud_ap_utils_win_unittest.cc",
-      "../browser/install_verification/win/module_info_unittest.cc",
-      "../browser/install_verification/win/module_list_unittest.cc",
-      "../browser/install_verification/win/module_verification_test.cc",
-      "../browser/install_verification/win/module_verification_test.h",
       "../browser/media/cdm_document_service_impl_test.cc",
       "../browser/media/media_foundation_service_monitor_unittest.cc",
       "../browser/metrics/antivirus_metrics_provider_win_unittest.cc",
@@ -7814,6 +7801,7 @@
       "//chrome/app:chrome_dll_resources",
       "//chrome/app:win_unit_tests",
       "//chrome/browser:chrome_process_finder",
+      "//chrome/browser/install_verification:unit_tests",
       "//chrome/browser/os_crypt:unit_tests",
       "//chrome/browser/shortcuts",
       "//chrome/browser/win:registry_watcher",
@@ -8191,6 +8179,8 @@
       "//chrome/browser/password_manager/android/grouped_affiliations:public",
       "//chrome/browser/password_manager/android/grouped_affiliations:test_utils",
       "//chrome/browser/password_manager/android/grouped_affiliations:unit_tests",
+      "//chrome/browser/predictors:unit_tests",
+      "//chrome/browser/predictors/lcp_critical_path_predictor:unit_tests",
       "//chrome/browser/readaloud/android:native",
       "//chrome/browser/reading_list/android:reading_list",
       "//chrome/browser/reading_list/android:unit_tests",
@@ -8600,6 +8590,8 @@
       "//chrome/browser/media:access_handler",
       "//chrome/browser/password_manager/password_change",
       "//chrome/browser/password_manager/password_change:unit_tests",
+      "//chrome/browser/predictors:unit_tests",
+      "//chrome/browser/predictors/lcp_critical_path_predictor:unit_tests",
       "//chrome/browser/private_ai:unit_tests",
       "//chrome/browser/record_replay:unit_tests",
       "//chrome/browser/resource_coordinator",
@@ -11218,6 +11210,7 @@
       "//chrome/browser/lifetime:termination_notification",
       "//chrome/browser/omnibox",
       "//chrome/browser/password_manager/factories",
+      "//chrome/browser/predictors",
       "//chrome/browser/privacy_sandbox:headers",
       "//chrome/browser/profiles:profile",
       "//chrome/browser/profiles:profile_io_data",
diff --git a/chrome/test/base/chrome_test_utils.cc b/chrome/test/base/chrome_test_utils.cc
index 745fb2e..118c457 100644
--- a/chrome/test/base/chrome_test_utils.cc
+++ b/chrome/test/base/chrome_test_utils.cc
@@ -8,6 +8,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "chrome/common/chrome_paths.h"
+#include "chrome/test/base/testing_browser_process.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "net/base/filename_util.h"
@@ -108,4 +109,10 @@
   return net::FilePathToFileURL(GetTestFilePath(dir, file));
 }
 
+TestingBrowserProcessDeathTestMixin::TestingBrowserProcessDeathTestMixin() {
+  if (!TestingBrowserProcess::GetGlobal()) {
+    TestingBrowserProcess::CreateInstance();
+  }
+}
+
 }  // namespace chrome_test_utils
diff --git a/chrome/test/base/chrome_test_utils.h b/chrome/test/base/chrome_test_utils.h
index 4a1b47a..bb0d3e6 100644
--- a/chrome/test/base/chrome_test_utils.h
+++ b/chrome/test/base/chrome_test_utils.h
@@ -78,6 +78,19 @@
 // The returned path is GURL format.
 GURL GetTestUrl(const base::FilePath& dir, const base::FilePath& file);
 
+// This class is inherited by unit test fixtures that leverage death tests with
+// a dependency on TestingBrowserProcess. It is necessary as currently death
+// tests will incompletely initialize the test environment, see bug below.
+// TODO(crbug.com/487292986): This should be eliminated once we update chromium
+// unit tests to avoid using listeners for test setup, or all existing death
+// test clients are updated to allow for the existence of the g_browser_process,
+// at which point this can be merged up into `ChromeUnitTestSuiteInitializer`.
+class TestingBrowserProcessDeathTestMixin {
+ public:
+  TestingBrowserProcessDeathTestMixin();
+  ~TestingBrowserProcessDeathTestMixin() = default;
+};
+
 }  // namespace chrome_test_utils
 
 #endif  // CHROME_TEST_BASE_CHROME_TEST_UTILS_H_
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_after_restart/service_worker_background.js b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_after_restart/service_worker_background.js
index 1a35e34d..6221797 100644
--- a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_after_restart/service_worker_background.js
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_after_restart/service_worker_background.js
@@ -2,14 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-chrome.webRequest.onBeforeRequest.addListener(({tabId, url}) => {
-  chrome.test.getConfig(function(config) {
-    const expectedUrl =
-          'http://127.0.0.1:' + config.testServer.port + '/empty.html';
-    chrome.test.assertEq(expectedUrl, url);
-    chrome.test.notifyPass();
-  });
-}, { urls: ["<all_urls>"], types: ["main_frame"] }, []);
+chrome.webRequest.onBeforeRequest.addListener(
+    ({tabId, url}) => {
+      chrome.test.getConfig(function(config) {
+        const expectedUrl =
+            'http://127.0.0.1:' + config.testServer.port + '/empty.html';
+        chrome.test.assertEq(expectedUrl, url);
+        chrome.test.notifyPass();
+      });
+    },
+    {urls: ['*://127.0.0.1/empty.html'], types: ['main_frame']},
+    ['extraHeaders']);
 
 // Tell the C++ side of the test that the listener was added.
 chrome.test.sendMessage('listener-added');
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_after_restart_remove_listener/service_worker_background.js b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_after_restart_remove_listener/service_worker_background.js
index 806a18d4..7cb338f 100644
--- a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_after_restart_remove_listener/service_worker_background.js
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_after_restart_remove_listener/service_worker_background.js
@@ -2,15 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-chrome.webRequest.onBeforeRequest.addListener(function listener({tabId, url}) {
-  chrome.test.getConfig(function(config) {
-    const expectedUrl =
-        'http://127.0.0.1:' + config.testServer.port + '/empty.html';
-    chrome.test.assertEq(expectedUrl, url);
-    chrome.webRequest.onBeforeRequest.removeListener(listener);
-    chrome.test.notifyPass();
-  });
-}, {urls: ['<all_urls>'], types: ['main_frame']}, []);
+chrome.webRequest.onBeforeRequest.addListener(
+    function listener({tabId, url}) {
+      chrome.test.getConfig(function(config) {
+        const expectedUrl =
+            'http://127.0.0.1:' + config.testServer.port + '/empty.html';
+        chrome.test.assertEq(expectedUrl, url);
+        chrome.webRequest.onBeforeRequest.removeListener(listener);
+        chrome.test.notifyPass();
+      });
+    },
+    {urls: ['*://127.0.0.1/empty.html'], types: ['main_frame']},
+    ['extraHeaders']);
 
 // Tell the C++ side of the test that the listener was added.
 chrome.test.sendMessage('listener-added');
diff --git a/chrome/test/data/sessions/file_with_incomplete_command b/chrome/test/data/sessions/file_with_incomplete_command
index 74934727..b04eab4 100644
--- a/chrome/test/data/sessions/file_with_incomplete_command
+++ b/chrome/test/data/sessions/file_with_incomplete_command
Binary files differ
diff --git a/chrome/test/data/web_apps/migration/migrate_from/manifest_suggest_new.json b/chrome/test/data/web_apps/migration/migrate_from/manifest_suggest_new.json
new file mode 100644
index 0000000..58d2214
--- /dev/null
+++ b/chrome/test/data/web_apps/migration/migrate_from/manifest_suggest_new.json
@@ -0,0 +1,17 @@
+{
+  "name": "Migrate From Updated Name",
+  "icons": [
+    {
+      "src": "192.png",
+      "sizes": "192x192",
+      "type": "image/png"
+    }
+  ],
+  "id": "web_apps/migration/migrate_from/manifest_id",
+  "start_url": "/web_apps/migration/migrate_from/suggest.html",
+  "display": "standalone",
+  "migrate_to": {
+    "id": "/web_apps/migration/migrate_to/manifest_id",
+    "install_url": "/web_apps/migration/migrate_to/suggest.html"
+  }
+}
\ No newline at end of file
diff --git a/chrome/test/data/web_apps/migration/migrate_from/suggest_new_manifest.html b/chrome/test/data/web_apps/migration/migrate_from/suggest_new_manifest.html
new file mode 100644
index 0000000..88cf6663
--- /dev/null
+++ b/chrome/test/data/web_apps/migration/migrate_from/suggest_new_manifest.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<html>
+<head>
+  <title>Migrate From - Suggested (New)</title>
+  <link rel="manifest" href="manifest_suggest_new.json">
+</head>
+<body>
+  <h1>This is the 'migrate from' app, with a new manifest.</h1>
+</body>
+</html>
\ No newline at end of file
diff --git a/chrome/test/data/web_apps/migration/migrate_to/manifest_update_trigger_no_update.json b/chrome/test/data/web_apps/migration/migrate_to/manifest_update_trigger_no_update.json
new file mode 100644
index 0000000..f223866
--- /dev/null
+++ b/chrome/test/data/web_apps/migration/migrate_to/manifest_update_trigger_no_update.json
@@ -0,0 +1,17 @@
+{
+  "name": "Migrate To Update Trigger No Update",
+  "icons": [
+    {
+      "src": "192.png",
+      "sizes": "192x192",
+      "type": "image/png"
+    }
+  ],
+  "id": "web_apps/migration/migrate_to/manifest_id",
+  "start_url": "update_trigger_no_update.html",
+  "display": "standalone",
+  "migrate_from": [{
+    "id": "/web_apps/migration/migrate_from/manifest_id",
+    "install_url": "/web_apps/migration/migrate_from/suggest.html"
+  }]
+}
\ No newline at end of file
diff --git a/chrome/test/data/web_apps/migration/migrate_to/manifest_update_trigger_with_update.json b/chrome/test/data/web_apps/migration/migrate_to/manifest_update_trigger_with_update.json
new file mode 100644
index 0000000..3b9e921
--- /dev/null
+++ b/chrome/test/data/web_apps/migration/migrate_to/manifest_update_trigger_with_update.json
@@ -0,0 +1,17 @@
+{
+  "name": "Migrate To Update Trigger With Update",
+  "icons": [
+    {
+      "src": "192.png",
+      "sizes": "192x192",
+      "type": "image/png"
+    }
+  ],
+  "id": "web_apps/migration/migrate_to/manifest_id",
+  "start_url": "update_trigger_with_update.html",
+  "display": "standalone",
+  "migrate_from": [{
+    "id": "/web_apps/migration/migrate_from/manifest_id",
+    "install_url": "/web_apps/migration/migrate_from/suggest_new_manifest.html"
+  }]
+}
\ No newline at end of file
diff --git a/chrome/test/data/web_apps/migration/migrate_to/update_trigger_no_update.html b/chrome/test/data/web_apps/migration/migrate_to/update_trigger_no_update.html
new file mode 100644
index 0000000..6bb831e
--- /dev/null
+++ b/chrome/test/data/web_apps/migration/migrate_to/update_trigger_no_update.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<html>
+<head>
+  <title>Migrate To Update Trigger (No Update)</title>
+  <link rel="manifest" href="manifest_update_trigger_no_update.json">
+</head>
+<body>
+  <h1>This is the 'migrate to' app, trigger no update.</h1>
+</body>
+</html>
\ No newline at end of file
diff --git a/chrome/test/data/web_apps/migration/migrate_to/update_trigger_with_update.html b/chrome/test/data/web_apps/migration/migrate_to/update_trigger_with_update.html
new file mode 100644
index 0000000..d8d61da
--- /dev/null
+++ b/chrome/test/data/web_apps/migration/migrate_to/update_trigger_with_update.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<html>
+<head>
+  <title>Migrate To Update Trigger (With Update)</title>
+  <link rel="manifest" href="manifest_update_trigger_with_update.json">
+</head>
+<body>
+  <h1>This is the 'migrate to' app, trigger with update.</h1>
+</body>
+</html>
\ No newline at end of file
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index de924c54..898f363c 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -506,6 +506,7 @@
     definitions += [
       "//tools/typescript/definitions/chrome_event.d.ts",
       "//tools/typescript/definitions/chrome_send.d.ts",
+      "//tools/typescript/definitions/chrome_histograms.d.ts",
       "//tools/typescript/definitions/metrics_private.d.ts",
       "//tools/typescript/definitions/settings_private.d.ts",
     ]
diff --git a/chrome/test/data/webui/build_webui_tests.gni b/chrome/test/data/webui/build_webui_tests.gni
index ed1c890..812dec54 100644
--- a/chrome/test/data/webui/build_webui_tests.gni
+++ b/chrome/test/data/webui/build_webui_tests.gni
@@ -158,17 +158,15 @@
     }
   }
 
-  if (defined(cc_test_files)) {
-    check_tests_referenced("check_tests_referenced") {
-      visibility = [ ":build_grdp" ]
-      in_folder = "."
-      cc_files = cc_test_files
-      ts_files = filter_include(files,
-                                [
-                                  "*_test.ts",
-                                  "*_test.js",
-                                ])
-    }
+  check_tests_referenced("check_tests_referenced") {
+    visibility = [ ":build_grdp" ]
+    in_folder = "."
+    cc_files = cc_test_files
+    ts_files = filter_include(files,
+                              [
+                                "*_test.ts",
+                                "*_test.js",
+                              ])
   }
 
   # This target is public so that it can be depended on by
@@ -198,8 +196,6 @@
       deps += [ ":lint" ]
     }
 
-    if (defined(cc_test_files)) {
-      deps += [ ":check_tests_referenced" ]
-    }
+    deps += [ ":check_tests_referenced" ]
   }
 }
diff --git a/chrome/test/data/webui/check_tests_referenced.gni b/chrome/test/data/webui/check_tests_referenced.gni
index de8cca2..719d5e2 100644
--- a/chrome/test/data/webui/check_tests_referenced.gni
+++ b/chrome/test/data/webui/check_tests_referenced.gni
@@ -23,7 +23,13 @@
     cc_files_normalized = []
     foreach(f, cc_files) {
       extension = get_path_info(f, "extension")
-      assert(extension == "cc")
+      if (!is_chromeos) {
+        assert(extension == "cc")
+      } else {
+        # On CrOS there are still old js2gtest tests so allow .js extension as
+        # well.
+        assert(extension == "cc" || extension == "js")
+      }
       cc_files_normalized += [ rebase_path(f, root_build_dir) ]
     }
 
diff --git a/chrome/test/data/webui/check_tests_referenced.py b/chrome/test/data/webui/check_tests_referenced.py
index 9c93e44..a8ecb92d 100755
--- a/chrome/test/data/webui/check_tests_referenced.py
+++ b/chrome/test/data/webui/check_tests_referenced.py
@@ -5,6 +5,7 @@
 
 import argparse
 import os
+import re
 import sys
 
 
@@ -28,7 +29,7 @@
     missing_files = []
     for ts_file in ts_files:
         basename = os.path.basename(ts_file).replace('.ts', '.js')
-        if '/' + basename not in cc_content and '"' + basename not in cc_content:
+        if re.search(rf'\b{basename}\b', cc_content) is None:
             missing_files.append(basename)
 
     if missing_files:
diff --git a/chrome/test/data/webui/chromeos/BUILD.gn b/chrome/test/data/webui/chromeos/BUILD.gn
index eb4de4b..4c6c1e3 100644
--- a/chrome/test/data/webui/chromeos/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/BUILD.gn
@@ -124,6 +124,16 @@
 build_webui_tests("build") {
   ts_composite = true
   ts_tsconfig_base = "tsconfig_base.json"
+  cc_test_files = [
+    "account_manager/account_manager_browsertest.js",
+    "cr_components_chromeos_v3_browsertest.js",
+    "cr_focus_row_behavior_interactive_test.js",
+    "crostini_installer_browsertest.js",
+    "internet_config_dialog_browsertest.js",
+    "internet_detail_dialog_browsertest.js",
+    "set_time_dialog/set_time_dialog_browsertest.js",
+    "sys_internals/all_tests.js",
+  ]
   files = [
     "chai_assert.js",
     "cr_focus_row_behavior_test.ts",
diff --git a/chrome/test/data/webui/chromeos/ash_common/post_message_api/BUILD.gn b/chrome/test/data/webui/chromeos/ash_common/post_message_api/BUILD.gn
index 9ae9dd5..600be9f 100644
--- a/chrome/test/data/webui/chromeos/ash_common/post_message_api/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/ash_common/post_message_api/BUILD.gn
@@ -9,8 +9,9 @@
 build_webui_tests("build") {
   resource_path_prefix = "post_message_api"
 
+  cc_test_files = [ "post_message_api_browsertest.cc" ]
   files = [
-    "post_message_api_client_test.ts",
+    "test_post_message_api_client.ts",
     "post_message_api_test.ts",
   ]
 
diff --git a/chrome/test/data/webui/chromeos/ash_common/post_message_api/iframe.html b/chrome/test/data/webui/chromeos/ash_common/post_message_api/iframe.html
index 677dcd2..d0654ba 100644
--- a/chrome/test/data/webui/chromeos/ash_common/post_message_api/iframe.html
+++ b/chrome/test/data/webui/chromeos/ash_common/post_message_api/iframe.html
@@ -1,6 +1,6 @@
 <html>
 <body>
-<script type="module" src="chrome://webui-test/post_message_api/post_message_api_client_test.js"></script>
+<script type="module" src="chrome://webui-test/post_message_api/test_post_message_api_client.js"></script>
 HELLO WORLD.
 </body>
 </html>
diff --git a/chrome/test/data/webui/chromeos/ash_common/post_message_api/post_message_api_client_test.ts b/chrome/test/data/webui/chromeos/ash_common/post_message_api/test_post_message_api_client.ts
similarity index 100%
rename from chrome/test/data/webui/chromeos/ash_common/post_message_api/post_message_api_client_test.ts
rename to chrome/test/data/webui/chromeos/ash_common/post_message_api/test_post_message_api_client.ts
diff --git a/chrome/test/data/webui/chromeos/borealis_installer/BUILD.gn b/chrome/test/data/webui/chromeos/borealis_installer/BUILD.gn
index 76fd720..e246145 100644
--- a/chrome/test/data/webui/chromeos/borealis_installer/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/borealis_installer/BUILD.gn
@@ -8,6 +8,7 @@
   ts_path_mappings = [ "chrome://borealis-installer/*|" + rebase_path(
                            "$root_gen_dir/chrome/browser/resources/chromeos/borealis_installer/tsc/*",
                            target_gen_dir) ]
+  cc_test_files = [ "borealis_installer_browsertest.js" ]
   files = [
     "borealis_installer_app_test.ts",
     "borealis_installer_error_dialog_test.ts",
diff --git a/chrome/test/data/webui/chromeos/cloud_upload/BUILD.gn b/chrome/test/data/webui/chromeos/cloud_upload/BUILD.gn
index 047a4f7..d2c8a19 100644
--- a/chrome/test/data/webui/chromeos/cloud_upload/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/cloud_upload/BUILD.gn
@@ -5,6 +5,13 @@
 import("../../build_webui_tests.gni")
 
 build_webui_tests("build_webui_tests") {
+  cc_test_files = [
+    "cloud_upload_dialog_browsertest.js",
+    "connect_onedrive_browsertest.js",
+    "file_handler_page_browsertest.js",
+    "move_confirmation_page_browsertest.js",
+  ]
+
   files = [
     "cloud_upload_dialog_test.ts",
     "cloud_upload_test_browser_proxy.ts",
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/BUILD.gn b/chrome/test/data/webui/chromeos/emoji_picker/BUILD.gn
index 9a841758..c07a4e4 100644
--- a/chrome/test/data/webui/chromeos/emoji_picker/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/emoji_picker/BUILD.gn
@@ -14,6 +14,7 @@
     "//third_party/polymer/v3_0:library",
     "//ui/webui/resources/js:build_ts",
   ]
+  cc_test_files = [ "emoji_picker_browsertest.js" ]
   files = [
     "emoji_picker_extension_categories.ts",
     "emoji_picker_extension_emoji_test.ts",
diff --git a/chrome/test/data/webui/chromeos/manage_mirrorsync/BUILD.gn b/chrome/test/data/webui/chromeos/manage_mirrorsync/BUILD.gn
index 6a5dc68..f9d9390 100644
--- a/chrome/test/data/webui/chromeos/manage_mirrorsync/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/manage_mirrorsync/BUILD.gn
@@ -14,6 +14,7 @@
                     target_gen_dir),
   ]
 
+  cc_test_files = [ "manage_mirrorsync_browsertest.js" ]
   files = [ "manage_mirrorsync_app_test.ts" ]
   ts_deps = [
     "..:build_ts",
diff --git a/chrome/test/data/webui/chromeos/office_fallback/BUILD.gn b/chrome/test/data/webui/chromeos/office_fallback/BUILD.gn
index ead0dfd..e43c0c61 100644
--- a/chrome/test/data/webui/chromeos/office_fallback/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/office_fallback/BUILD.gn
@@ -5,6 +5,7 @@
 import("../../build_webui_tests.gni")
 
 build_webui_tests("build_webui_tests") {
+  cc_test_files = [ "office_fallback_browsertest.js" ]
   files = [ "office_fallback_app_test.ts" ]
   ts_path_mappings =
       [ "chrome://office-fallback/*|" +
diff --git a/chrome/test/data/webui/contextual_tasks/composebox_test.ts b/chrome/test/data/webui/contextual_tasks/composebox_test.ts
index 8486cca9..30df581 100644
--- a/chrome/test/data/webui/contextual_tasks/composebox_test.ts
+++ b/chrome/test/data/webui/contextual_tasks/composebox_test.ts
@@ -156,28 +156,6 @@
     mockTimer.uninstall();
   });
 
-  /* Get file from `imageInput` if `fileType` is image;
-   * otherwise if pdf, then from files.
-   */
-  function getInputBasedOnFileType(fileType: string): HTMLInputElement {
-    return fileType === 'application/pdf' ? composebox.$.context.$.fileInput :
-                                            composebox.$.context.$.imageInput;
-  }
-
-  function getMockFileChangeEventForFileType(fileType: string): Event {
-    if (fileType === 'application/pdf') {
-      return new Event('change');
-    }
-
-    const mockFileChange = new Event('change', {bubbles: true});
-    // Read only.
-    Object.defineProperty(mockFileChange, 'target', {
-      writable: false,
-      value: composebox.$.context.$.imageInput,
-    });
-    return mockFileChange;
-  }
-
   async function uploadFileAndVerify(
       token: Object, file: File, expectedInitialFilesCount: number = 0) {
     // Assert initial file count if 0 -> carousel should not render.
@@ -193,9 +171,13 @@
     const dataTransfer = new DataTransfer();
     dataTransfer.items.add(file);
 
-    const input: HTMLInputElement = getInputBasedOnFileType(file.type);
-    input.files = dataTransfer.files;
-    input.dispatchEvent(getMockFileChangeEventForFileType(file.type));
+    composebox.$.context.$.fileInputs.dispatchEvent(
+      new CustomEvent('on-file-change', {
+          detail: {files: dataTransfer.files},
+          bubbles: true,
+          composed: true,
+        }));
+
     // Must call to upload. Await -> wait for it to be called once.
     await mockSearchboxPageHandler.whenCalled(ADD_FILE_CONTEXT_FN);
 
diff --git a/chrome/test/data/webui/cr_components/composebox/context_menu_entrypoint_test.ts b/chrome/test/data/webui/cr_components/composebox/context_menu_entrypoint_test.ts
index 0841e353..5daa834a 100644
--- a/chrome/test/data/webui/cr_components/composebox/context_menu_entrypoint_test.ts
+++ b/chrome/test/data/webui/cr_components/composebox/context_menu_entrypoint_test.ts
@@ -563,8 +563,8 @@
             entrypoint.shadowRoot.querySelectorAll<HTMLElement>(
                 '.multi-tab-icon');
         assertEquals(2, tabSelectors.length);
-        assertEquals('cr:add', tabSelectors[0]!.getAttribute('icon'));
-        assertEquals('cr:add', tabSelectors[1]!.getAttribute('icon'));
+        assertEquals('composebox:addCircle', tabSelectors[0]!.getAttribute('icon'));
+        assertEquals('composebox:addCircle', tabSelectors[1]!.getAttribute('icon'));
 
         // Act by adding tab 1 as context.
         entrypoint.disabledTabIds = new Map([[1, '1']]);
@@ -575,8 +575,8 @@
             entrypoint.shadowRoot.querySelectorAll<HTMLElement>(
                 '.multi-tab-icon');
         assertEquals(2, tabSelectors.length);
-        assertEquals('cr:check', tabSelectors[0]!.getAttribute('icon'));
-        assertEquals('cr:add', tabSelectors[1]!.getAttribute('icon'));
+        assertEquals('composebox:checkCircle', tabSelectors[0]!.getAttribute('icon'));
+        assertEquals('composebox:addCircle', tabSelectors[1]!.getAttribute('icon'));
       });
 
   test('multi-tab enabled does not close context menu', async () => {
diff --git a/chrome/test/data/webui/cr_components/cr_shortcut_input/cr_shortcut_input_test.ts b/chrome/test/data/webui/cr_components/cr_shortcut_input/cr_shortcut_input_test.ts
index ab75547..6ea1fde 100644
--- a/chrome/test/data/webui/cr_components/cr_shortcut_input/cr_shortcut_input_test.ts
+++ b/chrome/test/data/webui/cr_components/cr_shortcut_input/cr_shortcut_input_test.ts
@@ -76,20 +76,32 @@
     assertEquals('Ctrl + A', field.value);
     assertEquals('Ctrl+A', input.shortcut);
 
-    // Test clearing the shortcut.
-    const clearShortcutPromise = eventToPromise('shortcut-updated', input);
+    // Test that clicking edit preserves the last shortcut value.
     input.$.edit.click();
-    assertEquals(input.$.input, input.shadowRoot.activeElement);
+    await microtasksFinished();
+    assertEquals('', field.value);
+    assertEquals('Ctrl+A', input.shortcut);
+
+    // Test that ending capture using the escape key restores the value.
+    const stopInputCapturePromise =
+        eventToPromise('input-capture-change', input);
+    keyDownOn(field, 27);  // Escape key.
+    await stopInputCapturePromise;
+    assertEquals('Ctrl + A', field.value);
+    assertEquals('Ctrl+A', input.shortcut);
+
+    // Test that clicking clear erases the field value and the stored shortcut
+    // value.
+    const clearShortcutPromise = eventToPromise('shortcut-updated', input);
+    input.$.clear.click();
     event = await clearShortcutPromise;
     await microtasksFinished();
     assertEquals('', event.detail);
-    field.blur();
     assertEquals('', input.shortcut);
+    assertEquals('', field.value);
 
-    // The `input-capture-change` event should happen twice when the edit button
-    // is clicked. The first event is triggered when the mouse down happens and
-    // the input capture should stop. The second event occurs during mouse up
-    // which triggers the button to start the input capture again.
+    // The `input-capture-change` event should happen once when the edit button
+    // is clicked.
     const inputCaptureChangeResults: boolean[] = [];
     input.addEventListener('input-capture-change', (e) => {
       inputCaptureChangeResults.push((e as CustomEvent<boolean>).detail);
@@ -97,32 +109,51 @@
 
     input.$.edit.click();
     await microtasksFinished();
-    assertEquals(2, inputCaptureChangeResults.length);
-    assertFalse(inputCaptureChangeResults[0]!);
-    assertTrue(inputCaptureChangeResults[1]!);
+    assertEquals(1, inputCaptureChangeResults.length);
+    assertTrue(inputCaptureChangeResults[0]!);
+  });
 
-    // Test ending capture using the escape key.
-    const stopInputCapturePromise =
-        eventToPromise('input-capture-change', input);
+  test('ButtonDisabledStates', async function() {
+    // Initially shortcut is empty - clear button should be disabled.
+    assertTrue(input.$.clear.disabled);
+    assertFalse(input.$.edit.disabled);
+
+    // Set a shortcut.
+    input.shortcut = 'Ctrl+A';
+    await microtasksFinished();
+    assertFalse(input.$.clear.disabled);
+    assertFalse(input.$.edit.disabled);
+
+    // Start editing. During editing, the edit button should be disabled.
     input.$.edit.click();
-    keyDownOn(field, 27);  // Escape key.
-    event = await stopInputCapturePromise;
-    assertFalse(event.detail);
+    await microtasksFinished();
+    assertFalse(input.$.clear.disabled);
+    assertTrue(input.$.edit.disabled);
+
+    // Clear shortcut - the clear button should return to being disabled.
+    input.$.clear.click();
+    await microtasksFinished();
+    assertTrue(input.$.clear.disabled);
+    assertFalse(input.$.edit.disabled);
   });
 
   test('AriaLabelUpdates', async function() {
-    // Verify that the aria labels are initially empty
+    // Verify that the aria labels are initially empty.
     assertEquals('', input.$.input.ariaLabel);
     assertEquals('', input.$.edit.ariaLabel);
+    assertEquals('', input.$.clear.ariaLabel);
 
-    // Update the input and edit button aria labels
+    // Update the aria labels.
     const inputAriaLabel = 'input';
     const editButtonAriaLabel = 'edit';
+    const clearButtonAriaLabel = 'clear';
     input.inputAriaLabel = inputAriaLabel;
     input.editButtonAriaLabel = editButtonAriaLabel;
+    input.clearButtonAriaLabel = clearButtonAriaLabel;
     await microtasksFinished();
     assertEquals(inputAriaLabel, input.$.input.ariaLabel);
     assertEquals(editButtonAriaLabel, input.$.edit.ariaLabel);
+    assertEquals(clearButtonAriaLabel, input.$.clear.ariaLabel);
   });
 
   test('GetBubbleAnchor', function() {
diff --git a/chrome/test/data/webui/extensions/keyboard_shortcuts_test.ts b/chrome/test/data/webui/extensions/keyboard_shortcuts_test.ts
index 9242e871..d5e6af4c 100644
--- a/chrome/test/data/webui/extensions/keyboard_shortcuts_test.ts
+++ b/chrome/test/data/webui/extensions/keyboard_shortcuts_test.ts
@@ -168,27 +168,24 @@
     assertEquals('Ctrl+A', shortcutInput.shortcut);
 
     // Test clearing the shortcut.
-    shortcutInput.$.edit.click();
-    assertEquals(shortcutInput.$.input, shortcutInput.shadowRoot.activeElement);
+    shortcutInput.$.clear.click();
     arg = await testDelegate.whenCalled('updateExtensionCommandKeybinding');
     await microtasksFinished();
 
-    field.blur();
     testDelegate.reset();
     assertDeepEquals([oneCommand.id, oneCommand.commands[0]!.name, ''], arg);
     assertEquals('', shortcutInput.shortcut);
+    assertEquals('', field.value);
 
-    // The click event causes the input element to lose focus on mouse down
-    // but regains focus on mouse up after triggering the edit button on mouse
-    // up. This should ultimately result in shortcuts being suspended.
+    // The click event on the edit button should result in shortcuts handling
+    // being suspended.
     shortcutInput.$.edit.click();
     await testDelegate.whenCalled('setShortcutHandlingSuspended');
     await microtasksFinished();
     const shortcutSuspendedArgs =
         testDelegate.getArgs('setShortcutHandlingSuspended');
-    assertEquals(2, testDelegate.getCallCount('setShortcutHandlingSuspended'));
-    assertFalse(shortcutSuspendedArgs[0]);
-    assertTrue(shortcutSuspendedArgs[1]);
+    assertEquals(1, testDelegate.getCallCount('setShortcutHandlingSuspended'));
+    assertTrue(shortcutSuspendedArgs[0]);
     testDelegate.reset();
 
     // Test ending capture using the escape key.
diff --git a/chrome/test/data/webui/glic/browser_tests/glic_api_browsertest.ts b/chrome/test/data/webui/glic/browser_tests/glic_api_browsertest.ts
index b078f0f..383b7b8 100644
--- a/chrome/test/data/webui/glic/browser_tests/glic_api_browsertest.ts
+++ b/chrome/test/data/webui/glic/browser_tests/glic_api_browsertest.ts
@@ -2739,6 +2739,10 @@
         return 'TRUST_FIRST_ONBOARDING_ARM_1';
       case HostCapability.TRUST_FIRST_ONBOARDING_ARM2:
         return 'TRUST_FIRST_ONBOARDING_ARM_2';
+      case HostCapability.SHARE_ADDITIONAL_IMAGE_CONTEXT:
+        return 'SHARE_ADDITIONAL_IMAGE_CONTEXT';
+      case HostCapability.PDF_ZERO_STATE:
+        return 'PDF_ZERO_STATE';
       default:
         return 'NEW_ENUM_NOT_IMPLEMENTED';
     }
diff --git a/chrome/test/data/webui/metrics_test_support.ts b/chrome/test/data/webui/metrics_test_support.ts
index 9a3ea0c..91ed0d7 100644
--- a/chrome/test/data/webui/metrics_test_support.ts
+++ b/chrome/test/data/webui/metrics_test_support.ts
@@ -42,5 +42,23 @@
   chrome.metricsPrivate.recordSmallCount = (m, v) => metrics.record(m, v);
   chrome.metricsPrivate.recordMediumCount = (m, v) => metrics.record(m, v);
   chrome.metricsPrivate.recordTime = (m, v) => metrics.record(m, v);
+
+  // Mirror for chrome.histograms callers.
+  const histograms =
+      (chrome as any).histograms || ((chrome as any).histograms = {});
+  histograms.recordUserAction = (m: string) => metrics.record(m, 0);
+  histograms.recordBoolean = (m: string, v: boolean) => metrics.record(m, v);
+  histograms.recordPercentage = (m: string, v: number) => metrics.record(m, v);
+  histograms.recordSmallCount = (m: string, v: number) => metrics.record(m, v);
+  histograms.recordMediumCount = (m: string, v: number) => metrics.record(m, v);
+  histograms.recordCount = (m: string, v: number) => metrics.record(m, v);
+  histograms.recordTime = (m: string, v: number) => metrics.record(m, v);
+  histograms.recordMediumTime = (m: string, v: number) => metrics.record(m, v);
+  histograms.recordLongTime = (m: string, v: number) => metrics.record(m, v);
+  histograms.recordValue = (metric: {metricName: string}, v: number) =>
+      metrics.record(metric.metricName, v);
+  histograms.recordEnumerationValue = (m: string, v: number) =>
+      metrics.record(m, v);
+  histograms.recordSparseValue = (m: string, v: number) => metrics.record(m, v);
   return metrics;
 }
diff --git a/chrome/test/data/webui/new_tab_page/composebox/composebox.gni b/chrome/test/data/webui/new_tab_page/composebox/composebox.gni
index f54b5bb..1b10fe6c 100644
--- a/chrome/test/data/webui/new_tab_page/composebox/composebox.gni
+++ b/chrome/test/data/webui/new_tab_page/composebox/composebox.gni
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 composebox_test_files = [
+  "composebox/composebox_file_inputs_test.ts",
   "composebox/composebox_test.ts",
   "composebox/contextual_entrypoint_and_carousel_test.ts",
   "composebox/file_carousel_test.ts",
diff --git a/chrome/test/data/webui/new_tab_page/composebox/composebox_file_inputs_test.ts b/chrome/test/data/webui/new_tab_page/composebox/composebox_file_inputs_test.ts
new file mode 100644
index 0000000..2f388b615
--- /dev/null
+++ b/chrome/test/data/webui/new_tab_page/composebox/composebox_file_inputs_test.ts
@@ -0,0 +1,61 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {ComposeboxFileInputsElement} from 'chrome://new-tab-page/lazy_load.js';
+import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {eventToPromise} from 'chrome://webui-test/test_util.js';
+
+suite('NewTabPageComposeboxFileInputsTest', () => {
+  let fileUploadSlot: HTMLElement;
+  let fileInputsElement: ComposeboxFileInputsElement;
+
+  setup(() => {
+    document.body.innerHTML = window.trustedTypes!.emptyHTML;
+    fileInputsElement = new ComposeboxFileInputsElement();
+    fileUploadSlot = document.createElement('button');
+    fileInputsElement.appendChild(fileUploadSlot);
+    document.body.appendChild(fileInputsElement);
+  });
+
+  test('open image event clicks image input', async () => {
+    const imageUploadClickEventPromise =
+        eventToPromise('click', fileInputsElement.$.imageInput);
+    fileUploadSlot.dispatchEvent(
+        new CustomEvent('open-image-upload', {bubbles: true, composed: true}));
+    await imageUploadClickEventPromise;
+  });
+
+  test('open file event clicks file input', async () => {
+    const imageFileClickEventPromise =
+        eventToPromise('click', fileInputsElement.$.fileInput);
+    fileUploadSlot.dispatchEvent(
+        new CustomEvent('open-file-upload', {bubbles: true, composed: true}));
+    await imageFileClickEventPromise;
+  });
+
+  test('file change event is fired when file input changes', async () => {
+    // Arrange.
+    const dataTransfer = new DataTransfer();
+    dataTransfer.items.add(
+        new File(['foo'], 'foo.pdf', {type: 'application/pdf'}));
+    dataTransfer.items.add(
+        new File(['foo2'], 'foo2.pdf', {type: 'application/pdf'}));
+
+    // Act.
+    const whenFileChange = eventToPromise('on-file-change', fileInputsElement);
+    const mockFileChange = new Event('change', {bubbles: true});
+    Object.defineProperty(mockFileChange, 'target', {
+      writable: false,
+      value: fileInputsElement.$.fileInput,
+    });
+    fileInputsElement.$.fileInput.files = dataTransfer.files;
+    fileInputsElement.$.fileInput.dispatchEvent(mockFileChange);
+
+    // Assert
+    const event = await whenFileChange;
+    assertTrue(!!event);
+    assertEquals(event.detail.files, dataTransfer.files);
+    assertEquals(fileInputsElement.$.fileInput.value, '');
+  });
+});
diff --git a/chrome/test/data/webui/new_tab_page/composebox/composebox_test.ts b/chrome/test/data/webui/new_tab_page/composebox/composebox_test.ts
index eef417c..93ecbe3 100644
--- a/chrome/test/data/webui/new_tab_page/composebox/composebox_test.ts
+++ b/chrome/test/data/webui/new_tab_page/composebox/composebox_test.ts
@@ -162,8 +162,8 @@
 
   function getInputForFileType(fileType: string): HTMLInputElement {
     return fileType === 'application/pdf' ?
-        composeboxElement.$.context.$.fileInput :
-        composeboxElement.$.context.$.imageInput;
+        composeboxElement.$.context.$.fileInputs.$.fileInput :
+        composeboxElement.$.context.$.fileInputs.$.imageInput;
   }
 
   function getMockFileChangeEventForType(fileType: string): Event {
@@ -174,7 +174,7 @@
     const mockFileChange = new Event('change', {bubbles: true});
     Object.defineProperty(mockFileChange, 'target', {
       writable: false,
-      value: composeboxElement.$.context.$.imageInput,
+      value: composeboxElement.$.context.$.fileInputs.$.imageInput,
     });
     return mockFileChange;
   }
@@ -268,8 +268,10 @@
     const dataTransfer = new DataTransfer();
     dataTransfer.items.add(
         new File(['foo1'], 'foo1.pdf', {type: 'application/pdf'}));
-    composeboxElement.$.context.$.fileInput.files = dataTransfer.files;
-    composeboxElement.$.context.$.fileInput.dispatchEvent(new Event('change'));
+    composeboxElement.$.context.$.fileInputs.$.fileInput.files =
+        dataTransfer.files;
+    composeboxElement.$.context.$.fileInputs.$.fileInput.dispatchEvent(
+        new Event('change'));
 
     await searchboxHandler.whenCalled(ADD_FILE_CONTEXT_FN);
     await microtasksFinished();
@@ -555,8 +557,9 @@
     const dataTransfer = new DataTransfer();
     const file = new File(['foo'], 'foo.pdf', {type: 'application/pdf'});
     dataTransfer.items.add(file);
-    composeboxElement.$.context.$.fileInput.files = dataTransfer.files;
-    composeboxElement.$.context.$.fileInput.dispatchEvent(
+    composeboxElement.$.context.$.fileInputs.$.fileInput.files =
+        dataTransfer.files;
+    composeboxElement.$.context.$.fileInputs.$.fileInput.dispatchEvent(
         new Event('change'));
 
     await searchboxHandler.whenCalled(ADD_FILE_CONTEXT_FN);
@@ -610,11 +613,13 @@
     const mockFileChange = new Event('change', {bubbles: true});
     Object.defineProperty(mockFileChange, 'target', {
       writable: false,
-      value: composeboxElement.$.context.$.fileInput,
+      value: composeboxElement.$.context.$.fileInputs.$.fileInput,
     });
 
-    composeboxElement.$.context.$.fileInput.files = dataTransfer.files;
-    composeboxElement.$.context.$.fileInput.dispatchEvent(mockFileChange);
+    composeboxElement.$.context.$.fileInputs.$.fileInput.files =
+        dataTransfer.files;
+    composeboxElement.$.context.$.fileInputs.$.fileInput.dispatchEvent(
+        mockFileChange);
 
     await waitForAddFileCallCount(2);
     await composeboxElement.updateComplete;
@@ -771,11 +776,11 @@
     });
     createComposeboxElement();
     let clickCalled = false;
-    composeboxElement.$.context.$.imageInput.click = () => {
+    composeboxElement.$.context.$.fileInputs.$.imageInput.click = () => {
       clickCalled = true;
     };
     composeboxElement.$.context.$.contextEntrypoint.dispatchEvent(
-        new CustomEvent('open-image-upload'));
+        new CustomEvent('open-image-upload', {bubbles: true, composed: true}));
 
     // Assert.
     assertTrue(clickCalled);
@@ -787,11 +792,11 @@
     });
     createComposeboxElement();
     let clickCalled = false;
-    composeboxElement.$.context.$.fileInput.click = () => {
+    composeboxElement.$.context.$.fileInputs.$.fileInput.click = () => {
       clickCalled = true;
     };
     composeboxElement.$.context.$.contextEntrypoint.dispatchEvent(
-        new CustomEvent('open-file-upload'));
+        new CustomEvent('open-file-upload', {bubbles: true, composed: true}));
 
     // Assert.
     assertTrue(clickCalled);
@@ -835,8 +840,9 @@
         const pdfFile = new File(['foo'], 'foo.pdf', {type: 'application/pdf'});
         const dataTransfer = new DataTransfer();
         dataTransfer.items.add(pdfFile);
-        composeboxElement.$.context.$.fileInput.files = dataTransfer.files;
-        composeboxElement.$.context.$.fileInput.dispatchEvent(
+        composeboxElement.$.context.$.fileInputs.$.fileInput.files =
+            dataTransfer.files;
+        composeboxElement.$.context.$.fileInputs.$.fileInput.dispatchEvent(
             new Event('change'));
 
         await searchboxHandler.whenCalled(ADD_FILE_CONTEXT_FN);
@@ -860,7 +866,8 @@
         const dataTransfer2 = new DataTransfer();
         dataTransfer2.items.add(imageFile);
 
-        const imageInput = composeboxElement.$.context.$.imageInput;
+        const imageInput =
+            composeboxElement.$.context.$.fileInputs.$.imageInput;
         imageInput.files = dataTransfer2.files;
         imageInput.dispatchEvent(new Event('change'));
 
@@ -2852,8 +2859,9 @@
       const dataTransfer = new DataTransfer();
       const file = new File(['foo'], 'foo.pdf', {type: 'application/pdf'});
       dataTransfer.items.add(file);
-      composeboxElement.$.context.$.fileInput.files = dataTransfer.files;
-      composeboxElement.$.context.$.fileInput.dispatchEvent(
+      composeboxElement.$.context.$.fileInputs.$.fileInput.files =
+          dataTransfer.files;
+      composeboxElement.$.context.$.fileInputs.$.fileInput.dispatchEvent(
           new Event('change'));
 
       await searchboxHandler.whenCalled(ADD_FILE_CONTEXT_FN);
diff --git a/chrome/test/data/webui/new_tab_page/composebox/contextual_entrypoint_and_carousel_test.ts b/chrome/test/data/webui/new_tab_page/composebox/contextual_entrypoint_and_carousel_test.ts
index 129e9d69..81bcdca7 100644
--- a/chrome/test/data/webui/new_tab_page/composebox/contextual_entrypoint_and_carousel_test.ts
+++ b/chrome/test/data/webui/new_tab_page/composebox/contextual_entrypoint_and_carousel_test.ts
@@ -75,9 +75,9 @@
     await microtasksFinished();
 
     const imageUploadClickEventPromise =
-        eventToPromise('click', element.$.imageInput);
+        eventToPromise('click', element.$.fileInputs.$.imageInput);
     element.$.contextEntrypoint.dispatchEvent(
-        new CustomEvent('open-image-upload'));
+        new CustomEvent('open-image-upload', {bubbles: true, composed: true}));
     await imageUploadClickEventPromise;
   });
 
@@ -91,9 +91,9 @@
     await microtasksFinished();
 
     const fileUploadClickEventPromise =
-        eventToPromise('click', element.$.fileInput);
+        eventToPromise('click', element.$.fileInputs.$.fileInput);
     element.$.contextEntrypoint.dispatchEvent(
-        new CustomEvent('open-file-upload'));
+        new CustomEvent('open-file-upload', {bubbles: true, composed: true}));
     await fileUploadClickEventPromise;
   });
 
diff --git a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.cc b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.cc
index 6ffa370..09560dc 100644
--- a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.cc
+++ b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.cc
@@ -96,6 +96,11 @@
   RunTest("new_tab_page/composebox/file_thumbnail_test.js", "mocha.run()");
 }
 
+IN_PROC_BROWSER_TEST_F(NewTabPageTest, ComposeboxFileInputs) {
+  RunTest("new_tab_page/composebox/composebox_file_inputs_test.js",
+          "mocha.run()");
+}
+
 // TODO(crbug.com/452644435): Test is flaky on no_field_trial.
 IN_PROC_BROWSER_TEST_F(NewTabPageTest,
                        DISABLED_ContextualEntrypointAndCarousel) {
diff --git a/chrome/test/data/webui/omnibox_popup/aim_app_test.ts b/chrome/test/data/webui/omnibox_popup/aim_app_test.ts
index 9d6e92c..eb5de67f 100644
--- a/chrome/test/data/webui/omnibox_popup/aim_app_test.ts
+++ b/chrome/test/data/webui/omnibox_popup/aim_app_test.ts
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {ComposeboxContextAddedMethod} from '//resources/cr_components/search/constants.js';
 import {BrowserProxy, PageCallbackRouter, PageHandlerRemote} from 'chrome://omnibox-popup.top-chrome/omnibox_popup.js';
 import type {PageRemote} from 'chrome://omnibox-popup.top-chrome/omnibox_popup.js';
 import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
@@ -23,8 +22,6 @@
   }
 }
 
-const FAKE_TOKEN_STRING = '00000000000000001234567890ABCDEF';
-
 suite('AimAppTest', function() {
   let testProxy: TestAimBrowserProxy;
   let metrics: MetricsTracker;
@@ -161,38 +158,4 @@
     await microtasksFinished();
     assertTrue(glowAnimationPlayed);
   });
-
-  test('LogsMetricOnAddSearchContextWithAttachments', function() {
-    const app = document.createElement('omnibox-aim-app');
-    document.body.appendChild(app);
-
-    assertEquals(
-        0,
-        metrics.count(
-            'ContextualSearch.ContextAdded.ContextAddedMethod.Omnibox'));
-
-    // Set context with attachments.
-    app.$.composebox.addSearchContext({
-      input: 'test input',
-      attachments: [{
-        fileAttachment: {
-          uuid: FAKE_TOKEN_STRING,
-          name: 'test.pdf',
-          mimeType: 'application/pdf',
-          imageDataUrl: null,
-        },
-      }],
-      toolMode: 0,
-    });
-
-    assertEquals(
-        1,
-        metrics.count(
-            'ContextualSearch.ContextAdded.ContextAddedMethod.Omnibox'));
-    assertEquals(
-        1,
-        metrics.count(
-            'ContextualSearch.ContextAdded.ContextAddedMethod.Omnibox',
-            ComposeboxContextAddedMethod.CONTEXT_MENU));
-  });
 });
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn
index c29225f..4e607e1 100644
--- a/chrome/test/data/webui/settings/BUILD.gn
+++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -5,6 +5,11 @@
 import("../build_webui_tests.gni")
 
 build_webui_tests("build") {
+  cc_test_files = [
+    "settings_browsertest.cc",
+    "settings_focus_test.cc",
+  ]
+
   files = [
     "about_page_test.ts",
     "ai_history_search_subpage_test.ts",
diff --git a/chrome/test/data/webui/settings/glic_subpage_focus_test.ts b/chrome/test/data/webui/settings/glic_subpage_focus_test.ts
index baae826..51895e1 100644
--- a/chrome/test/data/webui/settings/glic_subpage_focus_test.ts
+++ b/chrome/test/data/webui/settings/glic_subpage_focus_test.ts
@@ -100,9 +100,9 @@
     assertEquals(1, glicBrowserProxy.getCallCount('getGlicShortcut'));
     assertEquals('⌃A', shortcutInput.shortcut);
 
-    // Clicking on the edit button should clear out the shortcut.
+    // Clicking on the clear button should clear out the shortcut.
     glicBrowserProxy.setGlicShortcutResponse('');
-    shortcutInput.$.edit.click();
+    shortcutInput.$.clear.click();
     let arg = await glicBrowserProxy.whenCalled('setGlicShortcut');
     await microtasksFinished();
     assertEquals('', arg);
@@ -110,6 +110,7 @@
     glicBrowserProxy.reset();
 
     // Verify that inputting an invalid shortcut doesn't update the shortcut.
+    shortcutInput.$.edit.click();
     keyDownOn(field, 65);
     await microtasksFinished();
     assertEquals(0, glicBrowserProxy.getCallCount('setGlicShortcut'));
@@ -137,9 +138,9 @@
         1, glicBrowserProxy.getCallCount('getGlicFocusToggleShortcut'));
     assertEquals('Alt+Shift+G', shortcutInput.shortcut);
 
-    // Clicking on the edit button should clear out the shortcut.
+    // Clicking on the clear button should clear out the shortcut.
     glicBrowserProxy.setGlicFocusToggleShortcutResponse('');
-    shortcutInput.$.edit.click();
+    shortcutInput.$.clear.click();
     let arg = await glicBrowserProxy.whenCalled('setGlicFocusToggleShortcut');
     await microtasksFinished();
     assertEquals('', arg);
@@ -147,6 +148,7 @@
     glicBrowserProxy.reset();
 
     // Verify that inputting an invalid shortcut doesn't update the shortcut.
+    shortcutInput.$.edit.click();
     keyDownOn(field, 65);
     await microtasksFinished();
     assertEquals(
@@ -214,11 +216,10 @@
         assertEquals('⌃A', field.value);
 
         // Act.
-        shortcutInput.$.edit.click();
+        shortcutInput.$.clear.click();
         await metricsBrowserProxy.whenCalled('recordBooleanHistogram');
         await microtasksFinished();
         glicBrowserProxy.setShortcutResponse(params.shortcut, /*response=*/ '');
-        keyDownOn(field, 27);  // Escape key.
         await microtasksFinished();
         assertEquals('', field.value);
 
@@ -247,7 +248,6 @@
 
         // Act.
         shortcutInput.$.edit.click();
-        await metricsBrowserProxy.whenCalled('recordBooleanHistogram');
         await microtasksFinished();
         glicBrowserProxy.setShortcutResponse(
             params.shortcut, /*response=*/ 'Ctrl + A');
@@ -258,8 +258,7 @@
         // Assert.
         booleanHistograms =
             await metricsBrowserProxy.getArgs('recordBooleanHistogram');
-        assertEquals(2, booleanHistograms.length);
-        verifyBooleanMetric(params.customizationMetric, false);
+        assertEquals(1, booleanHistograms.length);
         verifyBooleanMetric(params.customizationMetric, true);
         if (params.enablementPrefix) {
           userActions = await metricsBrowserProxy.getArgs('recordAction');
@@ -281,7 +280,6 @@
 
         // Act.
         shortcutInput.$.edit.click();
-        await metricsBrowserProxy.whenCalled('recordBooleanHistogram');
         await microtasksFinished();
         glicBrowserProxy.setShortcutResponse(params.shortcut, 'Ctrl + B');
         keyDownOn(field, 66, ['ctrl']);
@@ -290,8 +288,7 @@
         // Assert.
         booleanHistograms =
             await metricsBrowserProxy.getArgs('recordBooleanHistogram');
-        assertEquals(2, booleanHistograms.length);
-        verifyBooleanMetric(params.customizationMetric, true);
+        assertEquals(1, booleanHistograms.length);
         verifyBooleanMetric(params.customizationMetric, true);
         if (params.enablementPrefix) {
           userActions = await metricsBrowserProxy.getArgs('recordAction');
diff --git a/chrome/test/data/webui/settings/settings_browsertest.cc b/chrome/test/data/webui/settings/settings_browsertest.cc
index 0e9115b0..0543a195 100644
--- a/chrome/test/data/webui/settings/settings_browsertest.cc
+++ b/chrome/test/data/webui/settings/settings_browsertest.cc
@@ -343,6 +343,13 @@
 }
 #endif
 
+#if BUILDFLAG(IS_MAC)
+// TODO(crbug.com/486228089): Fix consistent failures and enable test.
+IN_PROC_BROWSER_TEST_F(SettingsTest, DISABLED_PasskeyEditDialog) {
+  RunTest("settings/passkey_edit_dialog_test.js", "mocha.run()");
+}
+#endif
+
 IN_PROC_BROWSER_TEST_F(SettingsTest, PaymentsSection) {
   RunTest("settings/payments_section_test.js", "mocha.run()");
 }
diff --git a/chrome/test/data/webui/tab_search/BUILD.gn b/chrome/test/data/webui/tab_search/BUILD.gn
index a998432..463523c 100644
--- a/chrome/test/data/webui/tab_search/BUILD.gn
+++ b/chrome/test/data/webui/tab_search/BUILD.gn
@@ -5,6 +5,11 @@
 import("../build_webui_tests.gni")
 
 build_webui_tests("build") {
+  cc_test_files = [
+    "tab_search_browsertest.cc",
+    "tab_search_focus_test.cc",
+  ]
+
   files = [
     "auto_tab_groups_page_test.ts",
     "declutter_page_test.ts",
diff --git a/chrome/test/webapps/coverage/coverage_cros.tsv b/chrome/test/webapps/coverage/coverage_cros.tsv
index 50f55ecd..2b3a9d50 100644
--- a/chrome/test/webapps/coverage/coverage_cros.tsv
+++ b/chrome/test/webapps/coverage/coverage_cros.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 59%, with partial coverage: 73%
+# Full coverage: 60%, with partial coverage: 74%
 install_omnibox_icon_Standalone🌕	launch_from_menu_option_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌕
 install_omnibox_icon_Standalone🌕	launch_from_launch_icon_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌕
 install_omnibox_icon_Standalone🌕	launch_from_chrome_apps_Standalone🌓	check_app_title_Standalone_StandaloneOriginal🌕
@@ -1877,18 +1877,312 @@
 install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
 install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
 install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
-install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌓	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌓	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌓	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌓	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌓	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌓	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌓	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌓	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌓	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌓	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌓	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌓	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	check_update_dialog_is_showing🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	check_update_dialog_is_showing🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	check_update_dialog_is_showing🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	check_update_dialog_is_showing🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	check_update_dialog_is_showing🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	check_update_dialog_is_showing🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_app_not_in_list_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_app_not_in_list_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_app_not_in_list_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_app_not_in_list_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_app_not_in_list_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_app_not_in_list_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_app_not_in_list_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_app_not_in_list_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_app_not_in_list_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_app_not_in_list_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_app_not_in_list_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_app_not_in_list_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndUninstall🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndCancelUninstall🌑	check_app_not_in_list_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndCancelUninstall🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndCancelUninstall🌑	check_app_not_in_list_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndCancelUninstall🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndCancelUninstall🌑	check_app_not_in_list_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndCancelUninstall🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndCancelUninstall🌑	check_app_not_in_list_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndCancelUninstall🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndCancelUninstall🌑	check_app_not_in_list_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndCancelUninstall🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndCancelUninstall🌑	check_app_not_in_list_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CancelDialogAndCancelUninstall🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CloseDialog🌑	check_app_not_in_list_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CloseDialog🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CloseDialog🌑	check_app_not_in_list_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CloseDialog🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CloseDialog🌑	check_app_not_in_list_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CloseDialog🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CloseDialog🌑	check_app_not_in_list_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CloseDialog🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CloseDialog🌑	check_app_not_in_list_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CloseDialog🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌓	check_app_in_list_windowed_Standalone🌓	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CloseDialog🌑	check_app_not_in_list_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_CloseDialog🌑	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_app_not_in_list_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_app_not_in_list_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_app_not_in_list_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_app_not_in_list_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_app_not_in_list_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_app_not_in_list_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_pwa_window_created_StandaloneMigratedForced_One🌑	check_app_in_list_windowed_StandaloneMigratedForced🌑	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌑	check_app_icon_StandaloneMigratedForced_Green🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_pwa_window_created_StandaloneMigratedForced_One🌑	check_app_in_list_windowed_StandaloneMigratedForced🌑	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌑	check_app_icon_StandaloneMigratedForced_Green🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_pwa_window_created_StandaloneMigratedForced_One🌑	check_app_in_list_windowed_StandaloneMigratedForced🌑	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌑	check_app_icon_StandaloneMigratedForced_Green🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_pwa_window_created_StandaloneMigratedForced_One🌑	check_app_in_list_windowed_StandaloneMigratedForced🌑	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌑	check_app_icon_StandaloneMigratedForced_Green🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_pwa_window_created_StandaloneMigratedForced_One🌑	check_app_in_list_windowed_StandaloneMigratedForced🌑	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌑	check_app_icon_StandaloneMigratedForced_Green🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌓	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌑	handle_update_dialog_response_AcceptUpdate🌑	check_pwa_window_created_StandaloneMigratedForced_One🌑	check_app_in_list_windowed_StandaloneMigratedForced🌑	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌑	check_app_icon_StandaloneMigratedForced_Green🌑
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌓	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌓	navigate_browser_StandaloneMigratedSuggested🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌓	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌓	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌓	navigate_browser_StandaloneMigratedForced🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌓	navigate_pwa_Standalone_StandaloneMigratedForced🌕	check_menu_button_pending_update_NotExpanded🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	launch_from_chrome_apps_Standalone🌓	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓	switch_profile_clients_Client1🌕	check_app_not_in_list_Standalone🌓	check_app_in_list_windowed_StandaloneMigratedSuggested🌓	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	launch_from_chrome_apps_Standalone🌓	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌓	switch_profile_clients_Client1🌕	check_platform_shortcut_not_exists_Standalone🌑	check_app_in_list_windowed_StandaloneMigratedSuggested🌑	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌑	check_app_icon_StandaloneMigratedSuggested_Red🌑
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	launch_from_chrome_apps_Standalone🌓	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑	switch_profile_clients_Client1🌑	check_app_not_in_list_Standalone🌑	check_app_in_list_windowed_StandaloneMigratedSuggested🌑	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌑	check_app_icon_StandaloneMigratedSuggested_Red🌑
diff --git a/chrome/test/webapps/coverage/coverage_linux.tsv b/chrome/test/webapps/coverage/coverage_linux.tsv
index e717396..13a159b 100644
--- a/chrome/test/webapps/coverage/coverage_linux.tsv
+++ b/chrome/test/webapps/coverage/coverage_linux.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 81%, with partial coverage: 95%
+# Full coverage: 82%, with partial coverage: 94%
 install_omnibox_icon_Standalone🌕	launch_from_menu_option_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌕
 install_omnibox_icon_Standalone🌕	launch_from_launch_icon_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌕
 install_omnibox_icon_Standalone🌕	launch_from_chrome_apps_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌕
@@ -1848,18 +1848,312 @@
 install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
 install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
 install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
-install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	check_menu_button_pending_update_NotExpanded🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕	switch_profile_clients_Client1🌕	check_app_not_in_list_Standalone🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕	switch_profile_clients_Client1🌕	check_platform_shortcut_not_exists_Standalone🌑	check_app_in_list_windowed_StandaloneMigratedSuggested🌑	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌑	check_app_icon_StandaloneMigratedSuggested_Red🌑
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑	switch_profile_clients_Client1🌑	check_app_not_in_list_Standalone🌑	check_app_in_list_windowed_StandaloneMigratedSuggested🌑	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌑	check_app_icon_StandaloneMigratedSuggested_Red🌑
@@ -1896,6 +2190,30 @@
 install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	set_open_in_tab_from_app_home_Standalone🌕	switch_profile_clients_Client1🌕	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_in_list_tabbed_StandaloneMigratedSuggested🌕
 install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	set_open_in_tab_from_app_home_Standalone🌕	switch_profile_clients_Client1🌕	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_in_list_tabbed_StandaloneMigratedSuggested🌕
 install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	set_open_in_tab_from_app_home_Standalone🌕	switch_profile_clients_Client1🌕	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_in_list_tabbed_StandaloneMigratedSuggested🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕	switch_profile_clients_Client1🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_not_in_list_Standalone🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕	switch_profile_clients_Client1🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_not_exists_Standalone🌑
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕	switch_profile_clients_Client1🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_not_in_list_Standalone🌕
diff --git a/chrome/test/webapps/coverage/coverage_mac.tsv b/chrome/test/webapps/coverage/coverage_mac.tsv
index 94a26b6..d926294 100644
--- a/chrome/test/webapps/coverage/coverage_mac.tsv
+++ b/chrome/test/webapps/coverage/coverage_mac.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 83%, with partial coverage: 96%
+# Full coverage: 84%, with partial coverage: 95%
 install_omnibox_icon_Standalone🌕	launch_from_menu_option_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌕
 install_omnibox_icon_Standalone🌕	launch_from_launch_icon_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌕
 install_omnibox_icon_Standalone🌕	launch_from_chrome_apps_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌕
@@ -1822,18 +1822,312 @@
 install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
 install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
 install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
-install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	check_menu_button_pending_update_NotExpanded🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕	switch_profile_clients_Client1🌕	check_app_not_in_list_Standalone🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕	switch_profile_clients_Client1🌕	check_platform_shortcut_not_exists_Standalone🌑	check_app_in_list_windowed_StandaloneMigratedSuggested🌑	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌑	check_app_icon_StandaloneMigratedSuggested_Red🌑
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑	switch_profile_clients_Client1🌑	check_app_not_in_list_Standalone🌑	check_app_in_list_windowed_StandaloneMigratedSuggested🌑	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌑	check_app_icon_StandaloneMigratedSuggested_Red🌑
@@ -1870,6 +2164,30 @@
 install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	set_open_in_tab_from_app_home_Standalone🌕	switch_profile_clients_Client1🌕	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_in_list_tabbed_StandaloneMigratedSuggested🌕
 install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	set_open_in_tab_from_app_home_Standalone🌕	switch_profile_clients_Client1🌕	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_in_list_tabbed_StandaloneMigratedSuggested🌕
 install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	set_open_in_tab_from_app_home_Standalone🌕	switch_profile_clients_Client1🌕	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_in_list_tabbed_StandaloneMigratedSuggested🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕	switch_profile_clients_Client1🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_not_in_list_Standalone🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕	switch_profile_clients_Client1🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_not_exists_Standalone🌑
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕	switch_profile_clients_Client1🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_not_in_list_Standalone🌕
diff --git a/chrome/test/webapps/coverage/coverage_win.tsv b/chrome/test/webapps/coverage/coverage_win.tsv
index 3e41230..5d3a0241 100644
--- a/chrome/test/webapps/coverage/coverage_win.tsv
+++ b/chrome/test/webapps/coverage/coverage_win.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 82%, with partial coverage: 95%
+# Full coverage: 82%, with partial coverage: 94%
 install_omnibox_icon_Standalone🌕	launch_from_menu_option_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌕
 install_omnibox_icon_Standalone🌕	launch_from_launch_icon_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌕
 install_omnibox_icon_Standalone🌕	launch_from_chrome_apps_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌕
@@ -1848,18 +1848,312 @@
 install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
 install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
 install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
-install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
-install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
-install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedSuggested_One🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneMigratedForced🌕	check_app_icon_StandaloneMigratedForced_Red🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CancelDialogAndCancelUninstall🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_app_not_in_list_StandaloneMigratedForced🌕	check_app_in_list_windowed_Standalone🌕	check_window_closed🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_CloseDialog🌕	check_platform_shortcut_not_exists_StandaloneMigratedForced🌑	check_app_in_list_windowed_Standalone🌑	check_window_closed🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	handle_update_dialog_response_AcceptUpdate🌕	check_pwa_window_created_StandaloneMigratedForced_One🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	check_menu_button_pending_update_NotExpanded🌕
+install_policy_app_Standalone_WithShortcut_Windowed_WebApp🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	check_menu_button_pending_update_NotExpanded🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕	switch_profile_clients_Client1🌕	check_app_not_in_list_Standalone🌕	check_app_in_list_windowed_StandaloneMigratedSuggested🌕	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌕	check_app_icon_StandaloneMigratedSuggested_Red🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_app_not_in_list_Standalone🌕	switch_profile_clients_Client1🌕	check_platform_shortcut_not_exists_Standalone🌑	check_app_in_list_windowed_StandaloneMigratedSuggested🌑	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌑	check_app_icon_StandaloneMigratedSuggested_Red🌑
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	check_platform_shortcut_not_exists_Standalone🌑	switch_profile_clients_Client1🌑	check_app_not_in_list_Standalone🌑	check_app_in_list_windowed_StandaloneMigratedSuggested🌑	check_app_title_StandaloneMigratedSuggested_StandaloneMigratedSuggested🌑	check_app_icon_StandaloneMigratedSuggested_Red🌑
@@ -1896,6 +2190,30 @@
 install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	set_open_in_tab_from_app_home_Standalone🌕	switch_profile_clients_Client1🌕	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_in_list_tabbed_StandaloneMigratedSuggested🌕
 install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	set_open_in_tab_from_app_home_Standalone🌕	switch_profile_clients_Client1🌕	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_in_list_tabbed_StandaloneMigratedSuggested🌕
 install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	set_open_in_tab_from_app_home_Standalone🌕	switch_profile_clients_Client1🌕	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_in_list_tabbed_StandaloneMigratedSuggested🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_browser_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_menu_option_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_launch_icon_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_chrome_apps_Standalone🌕	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
+install_menu_option_Standalone🌕	switch_profile_clients_Client2🌕	install_locally_Standalone🌓	launch_from_chrome_apps_Standalone🌕	navigate_pwa_Standalone_StandaloneMigratedForced🌕	close_pwa🌕	launch_from_platform_shortcut_Standalone🌓	check_update_dialog_is_showing🌕	handle_update_dialog_response_AcceptUpdate🌕	switch_profile_clients_Client1🌕	check_app_in_list_windowed_StandaloneMigratedForced🌕	check_app_title_StandaloneMigratedForced_StandaloneOriginal🌕	check_app_icon_StandaloneMigratedForced_Green🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕	switch_profile_clients_Client1🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_not_in_list_Standalone🌕
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕	switch_profile_clients_Client1🌕	manifest_update_add_migrate_to_Standalone_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_platform_shortcut_not_exists_Standalone🌑
 install_omnibox_icon_Standalone🌕	switch_profile_clients_Client2🌕	check_app_in_list_not_locally_installed_Standalone🌕	switch_profile_clients_Client1🌕	navigate_browser_StandaloneMigratedSuggested🌕	trigger_update_dialog_and_handle_response_AcceptUpdate🌕	switch_profile_clients_Client2🌕	check_app_not_in_list_Standalone🌕
diff --git a/chrome/test/webapps/data/critical_user_journeys.md b/chrome/test/webapps/data/critical_user_journeys.md
index 5ab28ea..e50229ec 100644
--- a/chrome/test/webapps/data/critical_user_journeys.md
+++ b/chrome/test/webapps/data/critical_user_journeys.md
@@ -613,17 +613,22 @@
 | WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | trigger_update_dialog_and_handle_response(CancelDialogAndUninstall) | check_app_not_installed(Standalone) |
 | WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedSuggested) | trigger_update_dialog_and_handle_response(CancelDialogAndUninstall) | check_app_not_installed(StandaloneMigratedSuggested) |
 | WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | trigger_update_dialog_and_handle_response(CancelDialogAndUninstall) | check_app_not_installed(StandaloneMigratedForced) |
-| WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedSuggested) | trigger_update_dialog_and_handle_response(AcceptUpdate) | check_app_in_list_windowed(StandaloneMigratedSuggested) | check_app_title(StandaloneMigratedSuggested, StandaloneMigratedSuggested) | check_app_icon(StandaloneMigratedSuggested, Red) |
-| WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | trigger_update_dialog_and_handle_response(AcceptUpdate) | check_app_in_list_windowed(StandaloneMigratedForced) | check_app_title(StandaloneMigratedForced, StandaloneMigratedForced) | check_app_icon(StandaloneMigratedForced, Red) |
+| WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedSuggested) | trigger_update_dialog_and_handle_response(AcceptUpdate) | check_pwa_window_created(StandaloneMigratedSuggested, One) | check_app_in_list_windowed(StandaloneMigratedSuggested) | check_app_title(StandaloneMigratedSuggested, StandaloneMigratedSuggested) | check_app_icon(StandaloneMigratedSuggested, Red) |
+| WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | trigger_update_dialog_and_handle_response(AcceptUpdate) | check_pwa_window_created(StandaloneMigratedForced, One) |check_app_in_list_windowed(StandaloneMigratedForced) | check_app_title(StandaloneMigratedForced, StandaloneMigratedForced) | check_app_icon(StandaloneMigratedForced, Red) |
 
-| # Verify forced migration dialog shows up on launch (not yet implemented)
-| #WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | check_update_dialog_is_showing |
-| #WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | handle_update_dialog_response(CancelDialogAndUninstall) | check_app_not_installed(Standalone) |
-| #WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | handle_update_dialog_response(CancelDialogAndUninstall) | check_app_not_installed(StandaloneMigratedForced) |
-| #WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | handle_update_dialog_response(AcceptUpdate) | check_app_not_installed(Standalone) |
-| #WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | handle_update_dialog_response(AcceptUpdate) | check_app_in_list_windowed(StandaloneMigratedForced) | check_app_title(StandaloneMigratedForced, StandaloneOriginal) | check_app_icon(StandaloneMigratedForced, Green) |
+| # Verify forced migration dialog shows up on launch
+| WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | check_update_dialog_is_showing |
+| WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | handle_update_dialog_response(CancelDialogAndUninstall) | check_app_not_installed(Standalone) |
+| WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | handle_update_dialog_response(CancelDialogAndUninstall) | check_app_not_installed(StandaloneMigratedForced) |
+| WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | handle_update_dialog_response(CancelDialogAndCancelUninstall) | check_app_not_installed(StandaloneMigratedForced) | check_app_in_list_windowed(Standalone) | check_window_closed |
+| WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | handle_update_dialog_response(CloseDialog) | check_app_not_installed(StandaloneMigratedForced) | check_app_in_list_windowed(Standalone) | check_window_closed |
+| WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | handle_update_dialog_response(AcceptUpdate) | check_app_not_installed(Standalone) |
+| WMLC | install_by_user | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | handle_update_dialog_response(AcceptUpdate) | check_pwa_window_created(StandaloneMigratedForced, One) | check_app_in_list_windowed(StandaloneMigratedForced) | check_app_title(StandaloneMigratedForced, StandaloneOriginal) | check_app_icon(StandaloneMigratedForced, Green) |
 
-| # TODO Force/policy installed apps
+| # Force/policy installed apps
+| WMLC | install_policy_app(Standalone, WithShortcut, Windowed, WebApp) | launch_from_chrome_apps | register_migration(Standalone, StandaloneMigratedSuggested) | check_menu_button_pending_update(NotExpanded) |
+| WMLC | install_policy_app(Standalone, WithShortcut, Windowed, WebApp) | launch_from_chrome_apps | register_migration(Standalone, StandaloneMigratedForced) | check_menu_button_pending_update(NotExpanded) |
+
 | # TODO Target already installed
 
 ### Sync
@@ -632,10 +637,11 @@
 | # Source app is fully installed in both profiles
 | WML | install_by_user | switch_profile_clients(Client2) | install_locally | launch_from_chrome_apps | register_migration(Standalone, StandaloneMigratedSuggested) | trigger_update_dialog_and_handle_response(AcceptUpdate) | check_app_not_installed(Standalone) | switch_profile_clients(Client1) | check_app_not_installed(Standalone) | check_app_in_list_windowed(StandaloneMigratedSuggested) | check_app_title(StandaloneMigratedSuggested, StandaloneMigratedSuggested) | check_app_icon(StandaloneMigratedSuggested, Red) |
 | WML | install_by_user | switch_profile_clients(Client2) | install_locally | set_open_in_tab | switch_profile_clients(Client1) | launch_from_chrome_apps | register_migration(Standalone, StandaloneMigratedSuggested) | trigger_update_dialog_and_handle_response(AcceptUpdate) | switch_profile_clients(Client2) | check_app_in_list_tabbed(StandaloneMigratedSuggested) |
-| #WML | install_by_user | switch_profile_clients(Client2) | install_locally | launch_from_chrome_apps | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | check_update_dialog_is_showing | handle_update_dialog_response(AcceptUpdate) | switch_profile_clients(Client1) | check_app_in_list_windowed(StandaloneMigratedForced) | check_app_title(StandaloneMigratedForced, StandaloneOriginal) | check_app_icon(StandaloneMigratedForced, Green) |
+| WML | install_by_user | switch_profile_clients(Client2) | install_locally | launch_from_chrome_apps | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | check_update_dialog_is_showing | handle_update_dialog_response(AcceptUpdate) | switch_profile_clients(Client1) | check_app_in_list_windowed(StandaloneMigratedForced) | check_app_title(StandaloneMigratedForced, StandaloneOriginal) | check_app_icon(StandaloneMigratedForced, Green) |
 
 | C | install_by_user | switch_profile_clients(Client2) | launch_from_chrome_apps | register_migration(Standalone, StandaloneMigratedSuggested) | trigger_update_dialog_and_handle_response(AcceptUpdate) | check_app_not_installed(Standalone) | switch_profile_clients(Client1) | check_app_not_installed(Standalone) | check_app_in_list_windowed(StandaloneMigratedSuggested) | check_app_title(StandaloneMigratedSuggested, StandaloneMigratedSuggested) | check_app_icon(StandaloneMigratedSuggested, Red) |
 | C | install_by_user | switch_profile_clients(Client2) | set_open_in_tab | switch_profile_clients(Client1) | launch_from_chrome_apps | register_migration(Standalone, StandaloneMigratedSuggested) | trigger_update_dialog_and_handle_response(AcceptUpdate) | switch_profile_clients(Client2) | check_app_in_list_tabbed(StandaloneMigratedSuggested) |
+| #TODO(crbug.com/487377880): Enable this test once migrated apps get the correct title/icon.
 | #C | install_by_user | switch_profile_clients(Client2) | launch_from_chrome_apps | register_migration(Standalone, StandaloneMigratedForced) | close_pwa | launch | check_update_dialog_is_showing | handle_update_dialog_response(AcceptUpdate) | switch_profile_clients(Client1) | check_app_in_list_windowed(StandaloneMigratedForced) | check_app_title(StandaloneMigratedForced, StandaloneOriginal) | check_app_icon(StandaloneMigratedForced, Green) |
 
 | # Source app is only fully installed in one profile
diff --git a/chrome/test/webapps/data/enums.md b/chrome/test/webapps/data/enums.md
index 9690eebe..2835c44 100644
--- a/chrome/test/webapps/data/enums.md
+++ b/chrome/test/webapps/data/enums.md
@@ -38,7 +38,7 @@
 | ShortcutOptions | WithShortcut | NoShortcut |
 | WindowOptions | Windowed | Browser |
 | InstallMode | WebApp* | WebShortcut |
-| UpdateDialogResponse | AcceptUpdate | CancelDialogAndUninstall | IgnoreDialog | | |
+| UpdateDialogResponse | AcceptUpdate | CancelDialogAndUninstall | CancelDialogAndCancelUninstall | IgnoreDialog | CloseDialog | |
 | SubAppInstallDialogOptions | UserAllow* | UserDeny | PolicyOverride |
 | ProfileName | Default | Profile2 |
 | MenuButtonState | ExpandedUpdateAvailable | NotExpanded |
diff --git a/chrome/utility/safe_browsing/archive_analysis_delegate.h b/chrome/utility/safe_browsing/archive_analysis_delegate.h
index 0a5b14a..7fe607e7 100644
--- a/chrome/utility/safe_browsing/archive_analysis_delegate.h
+++ b/chrome/utility/safe_browsing/archive_analysis_delegate.h
@@ -9,9 +9,12 @@
 
 #include "base/files/file.h"
 #include "chrome/utility/safe_browsing/zip_writer_delegate.h"
-#include "third_party/unrar/google/unrar_delegates.h"
 #include "third_party/zlib/google/zip_reader.h"
 
+#if USE_UNRAR
+#include "third_party/unrar/google/unrar_delegates.h"
+#endif
+
 namespace safe_browsing {
 
 // Delegate interface for abstracting archive analysis operations, specifically
diff --git a/chromeos/ash/components/dbus/concierge/fake_concierge_client.h b/chromeos/ash/components/dbus/concierge/fake_concierge_client.h
index d2f2d07..3ec08d1a 100644
--- a/chromeos/ash/components/dbus/concierge/fake_concierge_client.h
+++ b/chromeos/ash/components/dbus/concierge/fake_concierge_client.h
@@ -191,7 +191,11 @@
   const base::ObserverList<Observer>& observer_list() const {
     return observer_list_;
   }
-  const base::ObserverList<VmObserver>& vm_observer_list() const {
+  const base::ObserverList<
+      VmObserver,
+      /*check_empty=*/false,
+      base::ObserverListReentrancyPolicy::kAllowReentrancyUntriaged>&
+  vm_observer_list() const {
     return vm_observer_list_;
   }
   const base::ObserverList<DiskImageObserver>& disk_image_observer_list()
@@ -532,8 +536,12 @@
   base::ObserverList<Observer> observer_list_{
       ConciergeClient::kObserverListPolicy};
 
-  base::ObserverList<VmObserver> vm_observer_list_{
-      ConciergeClient::kObserverListPolicy};
+  // TODO(crbug.com/484371187): Investigate if reentrancy can be removed.
+  base::ObserverList<
+      VmObserver,
+      /*check_empty=*/false,
+      base::ObserverListReentrancyPolicy::kAllowReentrancyUntriaged>
+      vm_observer_list_{ConciergeClient::kObserverListPolicy};
 
   base::ObserverList<DiskImageObserver> disk_image_observer_list_{
       ConciergeClient::kObserverListPolicy};
diff --git a/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.cc b/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.cc
index b6fc7a2..4c365f8 100644
--- a/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.cc
+++ b/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.cc
@@ -296,8 +296,7 @@
       ShouldEnableWebRtc(data_usage,
                          NearbyConnectionsManager::PowerLevel::kHighPower),
       /*wifi_lan=*/
-      ShouldEnableWifiLan(data_usage, PowerLevel::kHighPower) &&
-          ::features::IsNearbyMdnsEnabled(),
+      ShouldEnableWifiLan(data_usage, PowerLevel::kHighPower),
       /*wifi_direct=*/
       base::FeatureList::IsEnabled(features::kNearbySharingWifiDirect));
   CD_LOG(VERBOSE, Feature::NEARBY_INFRA)
diff --git a/chromeos/ash/components/phonehub/browser_tabs_model_controller.cc b/chromeos/ash/components/phonehub/browser_tabs_model_controller.cc
index 3b311b4..d51b86d 100644
--- a/chromeos/ash/components/phonehub/browser_tabs_model_controller.cc
+++ b/chromeos/ash/components/phonehub/browser_tabs_model_controller.cc
@@ -19,16 +19,12 @@
     MutablePhoneModel* mutable_phone_model)
     : multidevice_setup_client_(multidevice_setup_client),
       cached_model_(/*is_tab_sync_enabled=*/false),
-      browser_tabs_model_provider_(browser_tabs_model_provider),
       mutable_phone_model_(mutable_phone_model) {
-  multidevice_setup_client_->AddObserver(this);
-  browser_tabs_model_provider_->AddObserver(this);
+  multidevice_setup_client_observation_.Observe(multidevice_setup_client_);
+  browser_tabs_model_provider_observation_.Observe(browser_tabs_model_provider);
 }
 
-BrowserTabsModelController::~BrowserTabsModelController() {
-  multidevice_setup_client_->RemoveObserver(this);
-  browser_tabs_model_provider_->RemoveObserver(this);
-}
+BrowserTabsModelController::~BrowserTabsModelController() = default;
 
 void BrowserTabsModelController::OnBrowserTabsUpdated(
     bool is_sync_enabled,
diff --git a/chromeos/ash/components/phonehub/browser_tabs_model_controller.h b/chromeos/ash/components/phonehub/browser_tabs_model_controller.h
index 82474c0..41ff681 100644
--- a/chromeos/ash/components/phonehub/browser_tabs_model_controller.h
+++ b/chromeos/ash/components/phonehub/browser_tabs_model_controller.h
@@ -6,6 +6,7 @@
 #define CHROMEOS_ASH_COMPONENTS_PHONEHUB_BROWSER_TABS_MODEL_CONTROLLER_H_
 
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
 #include "chromeos/ash/components/phonehub/browser_tabs_model.h"
 #include "chromeos/ash/components/phonehub/browser_tabs_model_provider.h"
 #include "chromeos/ash/components/phonehub/mutable_phone_model.h"
@@ -41,8 +42,13 @@
 
   raw_ptr<multidevice_setup::MultiDeviceSetupClient> multidevice_setup_client_;
   BrowserTabsModel cached_model_;
-  raw_ptr<BrowserTabsModelProvider> browser_tabs_model_provider_;
   raw_ptr<MutablePhoneModel, DanglingUntriaged> mutable_phone_model_;
+  base::ScopedObservation<multidevice_setup::MultiDeviceSetupClient,
+                          multidevice_setup::MultiDeviceSetupClient::Observer>
+      multidevice_setup_client_observation_{this};
+  base::ScopedObservation<BrowserTabsModelProvider,
+                          BrowserTabsModelProvider::Observer>
+      browser_tabs_model_provider_observation_{this};
 };
 
 }  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/camera_roll_manager_impl.cc b/chromeos/ash/components/phonehub/camera_roll_manager_impl.cc
index 016d43ef..f0c23c61 100644
--- a/chromeos/ash/components/phonehub/camera_roll_manager_impl.cc
+++ b/chromeos/ash/components/phonehub/camera_roll_manager_impl.cc
@@ -37,22 +37,17 @@
     multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client,
     secure_channel::ConnectionManager* connection_manager,
     std::unique_ptr<CameraRollDownloadManager> camera_roll_download_manager)
-    : message_receiver_(message_receiver),
-      message_sender_(message_sender),
+    : message_sender_(message_sender),
       multidevice_setup_client_(multidevice_setup_client),
       connection_manager_(connection_manager),
       camera_roll_download_manager_(std::move(camera_roll_download_manager)),
       thumbnail_decoder_(std::make_unique<CameraRollThumbnailDecoderImpl>()) {
-  message_receiver->AddObserver(this);
-  multidevice_setup_client_->AddObserver(this);
-  connection_manager_->AddObserver(this);
+  message_receiver_observation_.Observe(message_receiver);
+  multidevice_setup_client_observation_.Observe(multidevice_setup_client);
+  connection_manager_observation_.Observe(connection_manager);
 }
 
-CameraRollManagerImpl::~CameraRollManagerImpl() {
-  message_receiver_->RemoveObserver(this);
-  multidevice_setup_client_->RemoveObserver(this);
-  connection_manager_->RemoveObserver(this);
-}
+CameraRollManagerImpl::~CameraRollManagerImpl() = default;
 
 void CameraRollManagerImpl::DownloadItem(
     const proto::CameraRollItemMetadata& item_metadata) {
diff --git a/chromeos/ash/components/phonehub/camera_roll_manager_impl.h b/chromeos/ash/components/phonehub/camera_roll_manager_impl.h
index 1423a2b..b1a2a102 100644
--- a/chromeos/ash/components/phonehub/camera_roll_manager_impl.h
+++ b/chromeos/ash/components/phonehub/camera_roll_manager_impl.h
@@ -12,6 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
+#include "base/scoped_observation.h"
 #include "base/time/time.h"
 #include "chromeos/ash/components/phonehub/camera_roll_download_manager.h"
 #include "chromeos/ash/components/phonehub/camera_roll_manager.h"
@@ -95,7 +96,6 @@
   bool is_android_storage_granted_ = false;
   std::optional<base::TimeTicks> fetch_items_request_start_timestamp_;
 
-  raw_ptr<MessageReceiver> message_receiver_;
   raw_ptr<MessageSender> message_sender_;
   raw_ptr<multidevice_setup::MultiDeviceSetupClient> multidevice_setup_client_;
   raw_ptr<secure_channel::ConnectionManager> connection_manager_;
@@ -103,6 +103,15 @@
   std::unique_ptr<CameraRollDownloadManager> camera_roll_download_manager_;
   std::unique_ptr<CameraRollThumbnailDecoder> thumbnail_decoder_;
 
+  base::ScopedObservation<MessageReceiver, MessageReceiver::Observer>
+      message_receiver_observation_{this};
+  base::ScopedObservation<multidevice_setup::MultiDeviceSetupClient,
+                          multidevice_setup::MultiDeviceSetupClient::Observer>
+      multidevice_setup_client_observation_{this};
+  base::ScopedObservation<secure_channel::ConnectionManager,
+                          secure_channel::ConnectionManager::Observer>
+      connection_manager_observation_{this};
+
   base::WeakPtrFactory<CameraRollManagerImpl> weak_ptr_factory_{this};
   // WeakPtrFactory dedicated to thumbanil decoder callbacks that need to be
   // invalidated when the current item set updates.
diff --git a/chromeos/ash/components/phonehub/connection_scheduler_impl.cc b/chromeos/ash/components/phonehub/connection_scheduler_impl.cc
index 261a50b..bf547fa 100644
--- a/chromeos/ash/components/phonehub/connection_scheduler_impl.cc
+++ b/chromeos/ash/components/phonehub/connection_scheduler_impl.cc
@@ -36,13 +36,10 @@
   DCHECK(feature_status_provider_);
 
   current_feature_status_ = feature_status_provider_->GetStatus();
-  feature_status_provider_->AddObserver(this);
+  feature_status_provider_observation_.Observe(feature_status_provider);
 }
 
-ConnectionSchedulerImpl::~ConnectionSchedulerImpl() {
-  feature_status_provider_->RemoveObserver(this);
-  weak_ptr_factory_.InvalidateWeakPtrs();
-}
+ConnectionSchedulerImpl::~ConnectionSchedulerImpl() = default;
 
 void ConnectionSchedulerImpl::ScheduleConnectionNow(
     DiscoveryEntryPoint entry_point) {
diff --git a/chromeos/ash/components/phonehub/connection_scheduler_impl.h b/chromeos/ash/components/phonehub/connection_scheduler_impl.h
index 842489e..c723a84 100644
--- a/chromeos/ash/components/phonehub/connection_scheduler_impl.h
+++ b/chromeos/ash/components/phonehub/connection_scheduler_impl.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/scoped_observation.h"
 #include "base/time/time.h"
 #include "chromeos/ash/components/phonehub/connection_scheduler.h"
 #include "chromeos/ash/components/phonehub/feature_status.h"
@@ -57,6 +58,9 @@
   // Provides us the backoff timers for RequestConnection().
   net::BackoffEntry retry_backoff_;
   FeatureStatus current_feature_status_;
+  base::ScopedObservation<FeatureStatusProvider,
+                          FeatureStatusProvider::Observer>
+      feature_status_provider_observation_{this};
   base::WeakPtrFactory<ConnectionSchedulerImpl> weak_ptr_factory_{this};
 };
 
diff --git a/chromeos/ash/components/phonehub/cros_state_sender.cc b/chromeos/ash/components/phonehub/cros_state_sender.cc
index 21fa0de0..2ed642f 100644
--- a/chromeos/ash/components/phonehub/cros_state_sender.cc
+++ b/chromeos/ash/components/phonehub/cros_state_sender.cc
@@ -67,20 +67,15 @@
   DCHECK(phone_model_);
   DCHECK(retry_timer_);
 
-  connection_manager_->AddObserver(this);
-  multidevice_setup_client_->AddObserver(this);
+  connection_manager_observation_.Observe(connection_manager);
+  multidevice_setup_client_observation_.Observe(multidevice_setup_client);
   if (attestation_certificate_generator_) {
-    attestation_certificate_generator_->AddObserver(this);
+    attestation_certificate_generator_observation_.Observe(
+        attestation_certificate_generator_.get());
   }
 }
 
-CrosStateSender::~CrosStateSender() {
-  connection_manager_->RemoveObserver(this);
-  multidevice_setup_client_->RemoveObserver(this);
-  if (attestation_certificate_generator_) {
-    attestation_certificate_generator_->RemoveObserver(this);
-  }
-}
+CrosStateSender::~CrosStateSender() = default;
 
 void CrosStateSender::AttemptUpdateCrosState() {
   // Stop and cancel old timer if it is running, and reset the |retry_delay_| to
diff --git a/chromeos/ash/components/phonehub/cros_state_sender.h b/chromeos/ash/components/phonehub/cros_state_sender.h
index 876f0076..f543ddf 100644
--- a/chromeos/ash/components/phonehub/cros_state_sender.h
+++ b/chromeos/ash/components/phonehub/cros_state_sender.h
@@ -6,6 +6,7 @@
 #define CHROMEOS_ASH_COMPONENTS_PHONEHUB_CROS_STATE_SENDER_H_
 
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chromeos/ash/components/phonehub/public/cpp/attestation_certificate_generator.h"
@@ -76,6 +77,17 @@
   std::unique_ptr<AttestationCertificateGenerator>
       attestation_certificate_generator_;
   base::Time attestation_generating_start_time_;
+
+  base::ScopedObservation<secure_channel::ConnectionManager,
+                          secure_channel::ConnectionManager::Observer>
+      connection_manager_observation_{this};
+  base::ScopedObservation<multidevice_setup::MultiDeviceSetupClient,
+                          multidevice_setup::MultiDeviceSetupClient::Observer>
+      multidevice_setup_client_observation_{this};
+  base::ScopedObservation<AttestationCertificateGenerator,
+                          AttestationCertificateGenerator::Observer>
+      attestation_certificate_generator_observation_{this};
+
   base::WeakPtrFactory<CrosStateSender> weak_ptr_factory_{this};
 };
 
diff --git a/chromeos/ash/components/phonehub/feature_setup_response_processor.cc b/chromeos/ash/components/phonehub/feature_setup_response_processor.cc
index d8bb19de..1123c1a8c 100644
--- a/chromeos/ash/components/phonehub/feature_setup_response_processor.cc
+++ b/chromeos/ash/components/phonehub/feature_setup_response_processor.cc
@@ -14,17 +14,14 @@
 FeatureSetupResponseProcessor::FeatureSetupResponseProcessor(
     MessageReceiver* message_receiver,
     MultideviceFeatureAccessManager* multidevice_feature_access_manager)
-    : message_receiver_(message_receiver),
-      multidevice_feature_access_manager_(multidevice_feature_access_manager) {
-  DCHECK(message_receiver_);
+    : multidevice_feature_access_manager_(multidevice_feature_access_manager) {
+  DCHECK(message_receiver);
   DCHECK(multidevice_feature_access_manager_);
 
-  message_receiver_->AddObserver(this);
+  message_receiver_observation_.Observe(message_receiver);
 }
 
-FeatureSetupResponseProcessor::~FeatureSetupResponseProcessor() {
-  message_receiver_->RemoveObserver(this);
-}
+FeatureSetupResponseProcessor::~FeatureSetupResponseProcessor() = default;
 
 void FeatureSetupResponseProcessor::OnFeatureSetupResponseReceived(
     proto::FeatureSetupResponse response) {
diff --git a/chromeos/ash/components/phonehub/feature_setup_response_processor.h b/chromeos/ash/components/phonehub/feature_setup_response_processor.h
index 47d6cbef..ec390d8 100644
--- a/chromeos/ash/components/phonehub/feature_setup_response_processor.h
+++ b/chromeos/ash/components/phonehub/feature_setup_response_processor.h
@@ -6,6 +6,7 @@
 #define CHROMEOS_ASH_COMPONENTS_PHONEHUB_FEATURE_SETUP_RESPONSE_PROCESSOR_H_
 
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
 #include "chromeos/ash/components/phonehub/message_receiver.h"
 #include "chromeos/ash/components/phonehub/proto/phonehub_api.pb.h"
 
@@ -32,8 +33,9 @@
   void OnFeatureSetupResponseReceived(
       proto::FeatureSetupResponse response) override;
 
-  raw_ptr<MessageReceiver> message_receiver_;
   raw_ptr<MultideviceFeatureAccessManager> multidevice_feature_access_manager_;
+  base::ScopedObservation<MessageReceiver, MessageReceiver::Observer>
+      message_receiver_observation_{this};
 };
 
 }  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/feature_status_provider_impl.cc b/chromeos/ash/components/phonehub/feature_status_provider_impl.cc
index c719779..fdc54d6 100644
--- a/chromeos/ash/components/phonehub/feature_status_provider_impl.cc
+++ b/chromeos/ash/components/phonehub/feature_status_provider_impl.cc
@@ -149,16 +149,15 @@
       multidevice_setup_client_(multidevice_setup_client),
       connection_manager_(connection_manager),
       session_manager_(session_manager),
-      power_manager_client_(power_manager_client),
       phone_hub_structured_metrics_logger_(
           phone_hub_structured_metrics_logger) {
   DCHECK(session_manager_);
-  DCHECK(power_manager_client_);
-  device_sync_client_->AddObserver(this);
-  multidevice_setup_client_->AddObserver(this);
-  connection_manager_->AddObserver(this);
-  session_manager_->AddObserver(this);
-  power_manager_client_->AddObserver(this);
+  DCHECK(power_manager_client);
+  device_sync_client_observation_.Observe(device_sync_client);
+  multidevice_setup_client_observation_.Observe(multidevice_setup_client);
+  connection_manager_observation_.Observe(connection_manager);
+  session_manager_observation_.Observe(session_manager);
+  power_manager_client_observation_.Observe(power_manager_client);
 
   device::BluetoothAdapterFactory::Get()->GetAdapter(
       base::BindOnce(&FeatureStatusProviderImpl::OnBluetoothAdapterReceived,
@@ -167,16 +166,7 @@
   status_ = ComputeStatus();
 }
 
-FeatureStatusProviderImpl::~FeatureStatusProviderImpl() {
-  device_sync_client_->RemoveObserver(this);
-  multidevice_setup_client_->RemoveObserver(this);
-  connection_manager_->RemoveObserver(this);
-  if (bluetooth_adapter_) {
-    bluetooth_adapter_->RemoveObserver(this);
-  }
-  session_manager_->RemoveObserver(this);
-  power_manager_client_->RemoveObserver(this);
-}
+FeatureStatusProviderImpl::~FeatureStatusProviderImpl() = default;
 
 FeatureStatus FeatureStatusProviderImpl::GetStatus() const {
   PA_LOG(VERBOSE) << __func__ << ": status = " << *status_;
@@ -221,7 +211,7 @@
 void FeatureStatusProviderImpl::OnBluetoothAdapterReceived(
     scoped_refptr<device::BluetoothAdapter> bluetooth_adapter) {
   bluetooth_adapter_ = std::move(bluetooth_adapter);
-  bluetooth_adapter_->AddObserver(this);
+  bluetooth_adapter_observation_.Observe(bluetooth_adapter_.get());
 
   // If |status_| has not yet been set, this call occurred synchronously in the
   // constructor, so status_ has not yet been initialized.
diff --git a/chromeos/ash/components/phonehub/feature_status_provider_impl.h b/chromeos/ash/components/phonehub/feature_status_provider_impl.h
index c65ac7c..71ce4be 100644
--- a/chromeos/ash/components/phonehub/feature_status_provider_impl.h
+++ b/chromeos/ash/components/phonehub/feature_status_provider_impl.h
@@ -8,6 +8,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/scoped_observation.h"
 #include "chromeos/ash/components/phonehub/feature_status_provider.h"
 #include "chromeos/ash/components/phonehub/phone_hub_structured_metrics_logger.h"
 #include "chromeos/ash/services/device_sync/public/cpp/device_sync_client.h"
@@ -86,13 +87,31 @@
   raw_ptr<multidevice_setup::MultiDeviceSetupClient> multidevice_setup_client_;
   raw_ptr<secure_channel::ConnectionManager> connection_manager_;
   raw_ptr<session_manager::SessionManager> session_manager_;
-  raw_ptr<chromeos::PowerManagerClient> power_manager_client_;
   raw_ptr<PhoneHubStructuredMetricsLogger> phone_hub_structured_metrics_logger_;
 
   scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_;
   std::optional<FeatureStatus> status_;
   bool is_suspended_ = false;
 
+  base::ScopedObservation<device_sync::DeviceSyncClient,
+                          device_sync::DeviceSyncClient::Observer>
+      device_sync_client_observation_{this};
+  base::ScopedObservation<multidevice_setup::MultiDeviceSetupClient,
+                          multidevice_setup::MultiDeviceSetupClient::Observer>
+      multidevice_setup_client_observation_{this};
+  base::ScopedObservation<device::BluetoothAdapter,
+                          device::BluetoothAdapter::Observer>
+      bluetooth_adapter_observation_{this};
+  base::ScopedObservation<secure_channel::ConnectionManager,
+                          secure_channel::ConnectionManager::Observer>
+      connection_manager_observation_{this};
+  base::ScopedObservation<session_manager::SessionManager,
+                          session_manager::SessionManagerObserver>
+      session_manager_observation_{this};
+  base::ScopedObservation<chromeos::PowerManagerClient,
+                          chromeos::PowerManagerClient::Observer>
+      power_manager_client_observation_{this};
+
   base::WeakPtrFactory<FeatureStatusProviderImpl> weak_ptr_factory_{this};
 };
 
diff --git a/chromeos/ash/components/phonehub/invalid_connection_disconnector.cc b/chromeos/ash/components/phonehub/invalid_connection_disconnector.cc
index 59b56d3..d7a4c022 100644
--- a/chromeos/ash/components/phonehub/invalid_connection_disconnector.cc
+++ b/chromeos/ash/components/phonehub/invalid_connection_disconnector.cc
@@ -35,12 +35,10 @@
     : connection_manager_(connection_manager),
       phone_model_(phone_model),
       timer_(std::move(timer)) {
-  connection_manager_->AddObserver(this);
+  connection_manager_observation_.Observe(connection_manager);
 }
 
-InvalidConnectionDisconnector::~InvalidConnectionDisconnector() {
-  connection_manager_->RemoveObserver(this);
-}
+InvalidConnectionDisconnector::~InvalidConnectionDisconnector() = default;
 
 void InvalidConnectionDisconnector::OnConnectionStatusChanged() {
   timer_->Stop();
diff --git a/chromeos/ash/components/phonehub/invalid_connection_disconnector.h b/chromeos/ash/components/phonehub/invalid_connection_disconnector.h
index 7d96f36..ed863ca 100644
--- a/chromeos/ash/components/phonehub/invalid_connection_disconnector.h
+++ b/chromeos/ash/components/phonehub/invalid_connection_disconnector.h
@@ -6,6 +6,7 @@
 #define CHROMEOS_ASH_COMPONENTS_PHONEHUB_INVALID_CONNECTION_DISCONNECTOR_H_
 
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
 #include "chromeos/ash/services/secure_channel/public/cpp/client/connection_manager.h"
 
 namespace base {
@@ -50,6 +51,10 @@
   raw_ptr<secure_channel::ConnectionManager> connection_manager_;
   raw_ptr<PhoneModel> phone_model_;
   std::unique_ptr<base::OneShotTimer> timer_;
+
+  base::ScopedObservation<secure_channel::ConnectionManager,
+                          secure_channel::ConnectionManager::Observer>
+      connection_manager_observation_{this};
 };
 
 }  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/message_receiver_impl.cc b/chromeos/ash/components/phonehub/message_receiver_impl.cc
index ea34251..3ba2db9 100644
--- a/chromeos/ash/components/phonehub/message_receiver_impl.cc
+++ b/chromeos/ash/components/phonehub/message_receiver_impl.cc
@@ -59,17 +59,13 @@
 MessageReceiverImpl::MessageReceiverImpl(
     secure_channel::ConnectionManager* connection_manager,
     PhoneHubStructuredMetricsLogger* phone_hub_structured_metrics_logger)
-    : connection_manager_(connection_manager),
-      phone_hub_structured_metrics_logger_(
+    : phone_hub_structured_metrics_logger_(
           phone_hub_structured_metrics_logger) {
-  DCHECK(connection_manager_);
-
-  connection_manager_->AddObserver(this);
+  DCHECK(connection_manager);
+  connection_manager_observation_.Observe(connection_manager);
 }
 
-MessageReceiverImpl::~MessageReceiverImpl() {
-  connection_manager_->RemoveObserver(this);
-}
+MessageReceiverImpl::~MessageReceiverImpl() = default;
 
 void MessageReceiverImpl::OnMessageReceived(const std::string& payload) {
   // The first two bytes of |payload| is reserved for the header
diff --git a/chromeos/ash/components/phonehub/message_receiver_impl.h b/chromeos/ash/components/phonehub/message_receiver_impl.h
index cfb032b..11a46354 100644
--- a/chromeos/ash/components/phonehub/message_receiver_impl.h
+++ b/chromeos/ash/components/phonehub/message_receiver_impl.h
@@ -6,8 +6,8 @@
 #define CHROMEOS_ASH_COMPONENTS_PHONEHUB_MESSAGE_RECEIVER_IMPL_H_
 
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
 #include "chromeos/ash/components/phonehub/message_receiver.h"
-
 #include "chromeos/ash/components/phonehub/phone_hub_structured_metrics_logger.h"
 #include "chromeos/ash/services/secure_channel/public/cpp/client/connection_manager.h"
 
@@ -27,8 +27,10 @@
   // secure_channel::ConnectionManager::Observer:
   void OnMessageReceived(const std::string& payload) override;
 
-  raw_ptr<secure_channel::ConnectionManager> connection_manager_;
   raw_ptr<PhoneHubStructuredMetricsLogger> phone_hub_structured_metrics_logger_;
+  base::ScopedObservation<secure_channel::ConnectionManager,
+                          secure_channel::ConnectionManager::Observer>
+      connection_manager_observation_{this};
 };
 
 }  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/multidevice_setup_state_updater.cc b/chromeos/ash/components/phonehub/multidevice_setup_state_updater.cc
index 810cb84..53301ba 100644
--- a/chromeos/ash/components/phonehub/multidevice_setup_state_updater.cc
+++ b/chromeos/ash/components/phonehub/multidevice_setup_state_updater.cc
@@ -34,18 +34,16 @@
     : pref_service_(pref_service),
       multidevice_setup_client_(multidevice_setup_client),
       multidevice_feature_access_manager_(multidevice_feature_access_manager) {
-  multidevice_setup_client_->AddObserver(this);
-  multidevice_feature_access_manager_->AddObserver(this);
+  multidevice_setup_client_observation_.Observe(multidevice_setup_client);
+  multidevice_feature_access_manager_observation_.Observe(
+      multidevice_feature_access_manager);
   notification_access_status_ =
       multidevice_feature_access_manager_->GetNotificationAccessStatus();
   camera_roll_access_status_ =
       multidevice_feature_access_manager_->GetCameraRollAccessStatus();
 }
 
-MultideviceSetupStateUpdater::~MultideviceSetupStateUpdater() {
-  multidevice_setup_client_->RemoveObserver(this);
-  multidevice_feature_access_manager_->RemoveObserver(this);
-}
+MultideviceSetupStateUpdater::~MultideviceSetupStateUpdater() = default;
 
 void MultideviceSetupStateUpdater::OnNotificationAccessChanged() {
   MultideviceFeatureAccessManager::AccessStatus pervious_access_status =
diff --git a/chromeos/ash/components/phonehub/multidevice_setup_state_updater.h b/chromeos/ash/components/phonehub/multidevice_setup_state_updater.h
index 72e6dae..6c4dede 100644
--- a/chromeos/ash/components/phonehub/multidevice_setup_state_updater.h
+++ b/chromeos/ash/components/phonehub/multidevice_setup_state_updater.h
@@ -6,6 +6,7 @@
 #define CHROMEOS_ASH_COMPONENTS_PHONEHUB_MULTIDEVICE_SETUP_STATE_UPDATER_H_
 
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
 #include "chromeos/ash/components/phonehub/multidevice_feature_access_manager.h"
 #include "chromeos/ash/services/multidevice_setup/public/cpp/multidevice_setup_client.h"
 
@@ -55,6 +56,13 @@
   raw_ptr<MultideviceFeatureAccessManager> multidevice_feature_access_manager_;
   MultideviceFeatureAccessManager::AccessStatus notification_access_status_;
   MultideviceFeatureAccessManager::AccessStatus camera_roll_access_status_;
+
+  base::ScopedObservation<multidevice_setup::MultiDeviceSetupClient,
+                          multidevice_setup::MultiDeviceSetupClient::Observer>
+      multidevice_setup_client_observation_{this};
+  base::ScopedObservation<MultideviceFeatureAccessManager,
+                          MultideviceFeatureAccessManager::Observer>
+      multidevice_feature_access_manager_observation_{this};
 };
 
 }  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/notification_manager_impl.cc b/chromeos/ash/components/phonehub/notification_manager_impl.cc
index 97de0130..2595f229 100644
--- a/chromeos/ash/components/phonehub/notification_manager_impl.cc
+++ b/chromeos/ash/components/phonehub/notification_manager_impl.cc
@@ -25,12 +25,10 @@
   DCHECK(message_sender_);
   DCHECK(multidevice_setup_client_);
 
-  multidevice_setup_client_->AddObserver(this);
+  multidevice_setup_client_observation_.Observe(multidevice_setup_client);
 }
 
-NotificationManagerImpl::~NotificationManagerImpl() {
-  multidevice_setup_client_->RemoveObserver(this);
-}
+NotificationManagerImpl::~NotificationManagerImpl() = default;
 
 void NotificationManagerImpl::DismissNotification(int64_t notification_id) {
   PA_LOG(INFO) << "Dismissing notification with ID " << notification_id << ".";
diff --git a/chromeos/ash/components/phonehub/notification_manager_impl.h b/chromeos/ash/components/phonehub/notification_manager_impl.h
index 90652dd..ea35f8e8 100644
--- a/chromeos/ash/components/phonehub/notification_manager_impl.h
+++ b/chromeos/ash/components/phonehub/notification_manager_impl.h
@@ -8,6 +8,7 @@
 #include <optional>
 
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
 #include "chromeos/ash/components/phonehub/notification.h"
 #include "chromeos/ash/components/phonehub/notification_manager.h"
 #include "chromeos/ash/services/multidevice_setup/public/cpp/multidevice_setup_client.h"
@@ -44,6 +45,10 @@
   raw_ptr<multidevice_setup::MultiDeviceSetupClient> multidevice_setup_client_;
   std::optional<multidevice_setup::mojom::FeatureState>
       notifications_feature_status_;
+
+  base::ScopedObservation<multidevice_setup::MultiDeviceSetupClient,
+                          multidevice_setup::MultiDeviceSetupClient::Observer>
+      multidevice_setup_client_observation_{this};
 };
 
 }  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/onboarding_ui_tracker_impl.cc b/chromeos/ash/components/phonehub/onboarding_ui_tracker_impl.cc
index e69e413b..b845549 100644
--- a/chromeos/ash/components/phonehub/onboarding_ui_tracker_impl.cc
+++ b/chromeos/ash/components/phonehub/onboarding_ui_tracker_impl.cc
@@ -28,16 +28,13 @@
       multidevice_setup_client_(multidevice_setup_client),
       show_multidevice_setup_dialog_callback_(
           std::move(show_multidevice_setup_dialog_callback)) {
-  feature_status_provider_->AddObserver(this);
-  multidevice_setup_client_->AddObserver(this);
+  feature_status_provider_observation_.Observe(feature_status_provider);
+  multidevice_setup_client_observation_.Observe(multidevice_setup_client);
 
   should_show_onboarding_ui_ = ComputeShouldShowOnboardingUi();
 }
 
-OnboardingUiTrackerImpl::~OnboardingUiTrackerImpl() {
-  feature_status_provider_->RemoveObserver(this);
-  multidevice_setup_client_->RemoveObserver(this);
-}
+OnboardingUiTrackerImpl::~OnboardingUiTrackerImpl() = default;
 
 bool OnboardingUiTrackerImpl::ShouldShowOnboardingUi() const {
   return should_show_onboarding_ui_;
diff --git a/chromeos/ash/components/phonehub/onboarding_ui_tracker_impl.h b/chromeos/ash/components/phonehub/onboarding_ui_tracker_impl.h
index 125b6ce..6ef8ac11 100644
--- a/chromeos/ash/components/phonehub/onboarding_ui_tracker_impl.h
+++ b/chromeos/ash/components/phonehub/onboarding_ui_tracker_impl.h
@@ -7,6 +7,7 @@
 
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
 #include "chromeos/ash/components/phonehub/feature_status_provider.h"
 #include "chromeos/ash/components/phonehub/onboarding_ui_tracker.h"
 #include "chromeos/ash/services/multidevice_setup/public/cpp/multidevice_setup_client.h"
@@ -57,6 +58,13 @@
   raw_ptr<multidevice_setup::MultiDeviceSetupClient> multidevice_setup_client_;
   bool should_show_onboarding_ui_;
   base::RepeatingClosure show_multidevice_setup_dialog_callback_;
+
+  base::ScopedObservation<FeatureStatusProvider,
+                          FeatureStatusProvider::Observer>
+      feature_status_provider_observation_{this};
+  base::ScopedObservation<multidevice_setup::MultiDeviceSetupClient,
+                          multidevice_setup::MultiDeviceSetupClient::Observer>
+      multidevice_setup_client_observation_{this};
 };
 
 }  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/phone_hub_ui_readiness_recorder.cc b/chromeos/ash/components/phonehub/phone_hub_ui_readiness_recorder.cc
index 53fb64d..2f23699 100644
--- a/chromeos/ash/components/phonehub/phone_hub_ui_readiness_recorder.cc
+++ b/chromeos/ash/components/phonehub/phone_hub_ui_readiness_recorder.cc
@@ -14,14 +14,11 @@
     secure_channel::ConnectionManager* connection_manager)
     : feature_status_provider_(feature_status_provider),
       connection_manager_(connection_manager) {
-  feature_status_provider_->AddObserver(this);
-  connection_manager_->AddObserver(this);
+  feature_status_provider_observation_.Observe(feature_status_provider);
+  connection_manager_observation_.Observe(connection_manager);
 }
 
-PhoneHubUiReadinessRecorder::~PhoneHubUiReadinessRecorder() {
-  feature_status_provider_->RemoveObserver(this);
-  connection_manager_->RemoveObserver(this);
-}
+PhoneHubUiReadinessRecorder::~PhoneHubUiReadinessRecorder() = default;
 
 void PhoneHubUiReadinessRecorder::OnFeatureStatusChanged() {
   switch (feature_status_provider_->GetStatus()) {
diff --git a/chromeos/ash/components/phonehub/phone_hub_ui_readiness_recorder.h b/chromeos/ash/components/phonehub/phone_hub_ui_readiness_recorder.h
index 3f70bcb..a11be1b 100644
--- a/chromeos/ash/components/phonehub/phone_hub_ui_readiness_recorder.h
+++ b/chromeos/ash/components/phonehub/phone_hub_ui_readiness_recorder.h
@@ -7,6 +7,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
 #include "base/time/time.h"
 #include "chromeos/ash/components/phonehub/feature_status_provider.h"
 #include "chromeos/ash/services/secure_channel/public/cpp/client/connection_manager.h"
@@ -81,6 +82,13 @@
 
   ConnectionFlowState connection_flow_state_ =
       ConnectionFlowState::kSecureChannelNotConnected;
+
+  base::ScopedObservation<FeatureStatusProvider,
+                          FeatureStatusProvider::Observer>
+      feature_status_provider_observation_{this};
+  base::ScopedObservation<secure_channel::ConnectionManager,
+                          secure_channel::ConnectionManager::Observer>
+      connection_manager_observation_{this};
 };
 
 }  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/phone_status_processor.cc b/chromeos/ash/components/phonehub/phone_status_processor.cc
index 0eeb987..e293d1e 100644
--- a/chromeos/ash/components/phonehub/phone_status_processor.cc
+++ b/chromeos/ash/components/phonehub/phone_status_processor.cc
@@ -236,7 +236,6 @@
     PhoneHubStructuredMetricsLogger* phone_hub_structured_metrics_logger)
     : do_not_disturb_controller_(do_not_disturb_controller),
       feature_status_provider_(feature_status_provider),
-      message_receiver_(message_receiver),
       find_my_device_controller_(find_my_device_controller),
       multidevice_feature_access_manager_(multidevice_feature_access_manager),
       screen_lock_manager_(screen_lock_manager),
@@ -253,7 +252,7 @@
           phone_hub_structured_metrics_logger) {
   DCHECK(do_not_disturb_controller_);
   DCHECK(feature_status_provider_);
-  DCHECK(message_receiver_);
+  DCHECK(message_receiver);
   DCHECK(find_my_device_controller_);
   DCHECK(multidevice_feature_access_manager_);
   DCHECK(notification_processor_);
@@ -265,18 +264,14 @@
   DCHECK(phone_hub_ui_readiness_recorder_);
   DCHECK(phone_hub_structured_metrics_logger_);
 
-  message_receiver_->AddObserver(this);
-  feature_status_provider_->AddObserver(this);
-  multidevice_setup_client_->AddObserver(this);
+  message_receiver_observation_.Observe(message_receiver);
+  feature_status_provider_observation_.Observe(feature_status_provider_);
+  multidevice_setup_client_observation_.Observe(multidevice_setup_client_);
 
   MaybeSetPhoneModelName(multidevice_setup_client_->GetHostStatus().second);
 }
 
-PhoneStatusProcessor::~PhoneStatusProcessor() {
-  message_receiver_->RemoveObserver(this);
-  feature_status_provider_->RemoveObserver(this);
-  multidevice_setup_client_->RemoveObserver(this);
-}
+PhoneStatusProcessor::~PhoneStatusProcessor() = default;
 
 void PhoneStatusProcessor::ProcessReceivedNotifications(
     const RepeatedPtrField<proto::Notification>& notification_protos) {
diff --git a/chromeos/ash/components/phonehub/phone_status_processor.h b/chromeos/ash/components/phonehub/phone_status_processor.h
index 5358807..77b6228 100644
--- a/chromeos/ash/components/phonehub/phone_status_processor.h
+++ b/chromeos/ash/components/phonehub/phone_status_processor.h
@@ -8,6 +8,7 @@
 #include <google/protobuf/repeated_field.h>
 
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
 #include "base/timer/timer.h"
 #include "chromeos/ash/components/phonehub/app_stream_launcher_data_model.h"
 #include "chromeos/ash/components/phonehub/feature_status_provider.h"
@@ -116,7 +117,6 @@
 
   raw_ptr<DoNotDisturbController> do_not_disturb_controller_;
   raw_ptr<FeatureStatusProvider> feature_status_provider_;
-  raw_ptr<MessageReceiver> message_receiver_;
   raw_ptr<FindMyDeviceController> find_my_device_controller_;
   raw_ptr<MultideviceFeatureAccessManager> multidevice_feature_access_manager_;
   raw_ptr<ScreenLockManager> screen_lock_manager_;
@@ -133,6 +133,15 @@
   base::TimeTicks connection_initialized_timestamp_ = base::TimeTicks();
   bool has_received_first_app_list_update_ = false;
 
+  base::ScopedObservation<MessageReceiver, MessageReceiver::Observer>
+      message_receiver_observation_{this};
+  base::ScopedObservation<FeatureStatusProvider,
+                          FeatureStatusProvider::Observer>
+      feature_status_provider_observation_{this};
+  base::ScopedObservation<multidevice_setup::MultiDeviceSetupClient,
+                          multidevice_setup::MultiDeviceSetupClient::Observer>
+      multidevice_setup_client_observation_{this};
+
   base::WeakPtrFactory<PhoneStatusProcessor> weak_ptr_factory_{this};
 };
 
diff --git a/chromeos/ash/components/phonehub/ping_manager_impl.cc b/chromeos/ash/components/phonehub/ping_manager_impl.cc
index b88c8f0..e95f7d6 100644
--- a/chromeos/ash/components/phonehub/ping_manager_impl.cc
+++ b/chromeos/ash/components/phonehub/ping_manager_impl.cc
@@ -25,21 +25,17 @@
     MessageSender* message_sender)
     : connection_manager_(connection_manager),
       feature_status_provider_(feature_status_provider),
-      message_receiver_(message_receiver),
       message_sender_(message_sender) {
   DCHECK(connection_manager);
   DCHECK(feature_status_provider);
   DCHECK(message_receiver);
   DCHECK(message_sender);
 
-  feature_status_provider_->AddObserver(this);
-  message_receiver_->AddObserver(this);
+  feature_status_provider_observation_.Observe(feature_status_provider);
+  message_receiver_observation_.Observe(message_receiver);
 }
 
-PingManagerImpl::~PingManagerImpl() {
-  feature_status_provider_->RemoveObserver(this);
-  message_receiver_->RemoveObserver(this);
-}
+PingManagerImpl::~PingManagerImpl() = default;
 
 void PingManagerImpl::OnPhoneStatusSnapshotReceived(
     proto::PhoneStatusSnapshot phone_status_snapshot) {
diff --git a/chromeos/ash/components/phonehub/ping_manager_impl.h b/chromeos/ash/components/phonehub/ping_manager_impl.h
index bcfb8b9..cbe49f9ce 100644
--- a/chromeos/ash/components/phonehub/ping_manager_impl.h
+++ b/chromeos/ash/components/phonehub/ping_manager_impl.h
@@ -6,6 +6,7 @@
 #define CHROMEOS_ASH_COMPONENTS_PHONEHUB_PING_MANAGER_IMPL_H_
 
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
 #include "base/timer/timer.h"
 #include "chromeos/ash/components/phonehub/feature_status.h"
 #include "chromeos/ash/components/phonehub/feature_status_provider.h"
@@ -72,10 +73,15 @@
   base::TimeTicks ping_sent_timestamp_;
   raw_ptr<secure_channel::ConnectionManager> connection_manager_;
   raw_ptr<FeatureStatusProvider> feature_status_provider_;
-  raw_ptr<MessageReceiver> message_receiver_;
   raw_ptr<MessageSender> message_sender_;
   bool is_ping_supported_by_phone_ = false;
   bool is_waiting_for_response_ = false;
+
+  base::ScopedObservation<FeatureStatusProvider,
+                          FeatureStatusProvider::Observer>
+      feature_status_provider_observation_{this};
+  base::ScopedObservation<MessageReceiver, MessageReceiver::Observer>
+      message_receiver_observation_{this};
 };
 
 }  // namespace ash::phonehub
diff --git a/chromeos/ash/components/phonehub/recent_apps_interaction_handler_impl.cc b/chromeos/ash/components/phonehub/recent_apps_interaction_handler_impl.cc
index 0d39d98a..2e740a4 100644
--- a/chromeos/ash/components/phonehub/recent_apps_interaction_handler_impl.cc
+++ b/chromeos/ash/components/phonehub/recent_apps_interaction_handler_impl.cc
@@ -49,18 +49,12 @@
     : pref_service_(pref_service),
       multidevice_setup_client_(multidevice_setup_client),
       multidevice_feature_access_manager_(multidevice_feature_access_manager) {
-  multidevice_setup_client_->AddObserver(this);
-  multidevice_feature_access_manager_->AddObserver(this);
+  multidevice_setup_client_observation_.Observe(multidevice_setup_client);
+  multidevice_feature_access_manager_observation_.Observe(
+      multidevice_feature_access_manager);
 }
 
-RecentAppsInteractionHandlerImpl::~RecentAppsInteractionHandlerImpl() {
-  if (eche_connection_status_handler_) {
-    eche_connection_status_handler_->RemoveObserver(this);
-  }
-
-  multidevice_setup_client_->RemoveObserver(this);
-  multidevice_feature_access_manager_->RemoveObserver(this);
-}
+RecentAppsInteractionHandlerImpl::~RecentAppsInteractionHandlerImpl() = default;
 
 void RecentAppsInteractionHandlerImpl::AddRecentAppClickObserver(
     RecentAppClickObserver* observer) {
@@ -108,14 +102,11 @@
 
 void RecentAppsInteractionHandlerImpl::SetConnectionStatusHandler(
     eche_app::EcheConnectionStatusHandler* eche_connection_status_handler) {
-  if (eche_connection_status_handler_) {
-    eche_connection_status_handler_->RemoveObserver(this);
-  }
+  eche_connection_status_handler_observation_.Reset();
 
-  eche_connection_status_handler_ = eche_connection_status_handler;
-
-  if (eche_connection_status_handler_) {
-    eche_connection_status_handler_->AddObserver(this);
+  if (eche_connection_status_handler) {
+    eche_connection_status_handler_observation_.Observe(
+        eche_connection_status_handler);
   }
 }
 
diff --git a/chromeos/ash/components/phonehub/recent_apps_interaction_handler_impl.h b/chromeos/ash/components/phonehub/recent_apps_interaction_handler_impl.h
index 7c9e2d37..8bff89b5 100644
--- a/chromeos/ash/components/phonehub/recent_apps_interaction_handler_impl.h
+++ b/chromeos/ash/components/phonehub/recent_apps_interaction_handler_impl.h
@@ -12,6 +12,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
+#include "base/scoped_observation.h"
 #include "base/time/time.h"
 #include "chromeos/ash/components/phonehub/multidevice_feature_access_manager.h"
 #include "chromeos/ash/components/phonehub/notification.h"
@@ -110,8 +111,16 @@
   raw_ptr<PrefService> pref_service_;
   raw_ptr<multidevice_setup::MultiDeviceSetupClient> multidevice_setup_client_;
   raw_ptr<MultideviceFeatureAccessManager> multidevice_feature_access_manager_;
-  raw_ptr<eche_app::EcheConnectionStatusHandler>
-      eche_connection_status_handler_ = nullptr;
+
+  base::ScopedObservation<multidevice_setup::MultiDeviceSetupClient,
+                          multidevice_setup::MultiDeviceSetupClient::Observer>
+      multidevice_setup_client_observation_{this};
+  base::ScopedObservation<MultideviceFeatureAccessManager,
+                          MultideviceFeatureAccessManager::Observer>
+      multidevice_feature_access_manager_observation_{this};
+  base::ScopedObservation<eche_app::EcheConnectionStatusHandler,
+                          eche_app::EcheConnectionStatusHandler::Observer>
+      eche_connection_status_handler_observation_{this};
 
   base::WeakPtrFactory<RecentAppsInteractionHandlerImpl> weak_ptr_factory_{
       this};
diff --git a/chromeos/ash/components/phonehub/tether_controller_impl.cc b/chromeos/ash/components/phonehub/tether_controller_impl.cc
index 829b3403..d15dfb3 100644
--- a/chromeos/ash/components/phonehub/tether_controller_impl.cc
+++ b/chromeos/ash/components/phonehub/tether_controller_impl.cc
@@ -77,8 +77,8 @@
       cros_network_config_.BindNewPipeAndPassReceiver());
   cros_network_config_->AddObserver(receiver_.BindNewPipeAndPassRemote());
 
-  phone_model_->AddObserver(this);
-  multidevice_setup_client_->AddObserver(this);
+  phone_model_observation_.Observe(phone_model);
+  multidevice_setup_client_observation_.Observe(multidevice_setup_client);
 
   // Compute current status.
   status_ = ComputeStatus();
@@ -87,10 +87,7 @@
   FetchVisibleTetherNetwork();
 }
 
-TetherControllerImpl::~TetherControllerImpl() {
-  phone_model_->RemoveObserver(this);
-  multidevice_setup_client_->RemoveObserver(this);
-}
+TetherControllerImpl::~TetherControllerImpl() = default;
 
 TetherController::Status TetherControllerImpl::GetStatus() const {
   PA_LOG(VERBOSE) << __func__ << ": status = " << status_;
diff --git a/chromeos/ash/components/phonehub/tether_controller_impl.h b/chromeos/ash/components/phonehub/tether_controller_impl.h
index b3cc120..07bab5ff 100644
--- a/chromeos/ash/components/phonehub/tether_controller_impl.h
+++ b/chromeos/ash/components/phonehub/tether_controller_impl.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/scoped_observation.h"
 #include "chromeos/ash/components/phonehub/phone_model.h"
 #include "chromeos/ash/components/phonehub/tether_controller.h"
 #include "chromeos/ash/services/multidevice_setup/public/cpp/multidevice_setup_client.h"
@@ -174,6 +175,12 @@
   mojo::Remote<chromeos::network_config::mojom::CrosNetworkConfig>
       cros_network_config_;
 
+  base::ScopedObservation<PhoneModel, PhoneModel::Observer>
+      phone_model_observation_{this};
+  base::ScopedObservation<multidevice_setup::MultiDeviceSetupClient,
+                          multidevice_setup::MultiDeviceSetupClient::Observer>
+      multidevice_setup_client_observation_{this};
+
   base::WeakPtrFactory<TetherControllerImpl> weak_ptr_factory_{this};
 };
 
diff --git a/chromeos/printing/usb_printer_id.cc b/chromeos/printing/usb_printer_id.cc
index 605a227..b94368c 100644
--- a/chromeos/printing/usb_printer_id.cc
+++ b/chromeos/printing/usb_printer_id.cc
@@ -84,7 +84,7 @@
       continue;
     }
 
-    ret[term.first] = values;
+    ret[term.first] = std::move(values);
   }
   ret[kChromeOsRawId].emplace_back(std::move(printer_id));
 
diff --git a/clank b/clank
index 6ee72ff..1826169 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit 6ee72ff5ecc3b2013b0837ea8c3c3a721b12838b
+Subproject commit 1826169221c2df97bc9334bb042069f26774003a
diff --git a/components/browser_ui/util/android/BUILD.gn b/components/browser_ui/util/android/BUILD.gn
index a331eaa..6780f94 100644
--- a/components/browser_ui/util/android/BUILD.gn
+++ b/components/browser_ui/util/android/BUILD.gn
@@ -12,6 +12,7 @@
     "java/src/org/chromium/components/browser_ui/util/BrowserControlsVisibilityDelegate.java",
     "java/src/org/chromium/components/browser_ui/util/BrowserUiUtilsCachedFlags.java",
     "java/src/org/chromium/components/browser_ui/util/ChromeItemPickerExtras.java",
+    "java/src/org/chromium/components/browser_ui/util/ChromeItemPickerUtils.java",
     "java/src/org/chromium/components/browser_ui/util/ComposedBrowserControlsVisibilityDelegate.java",
     "java/src/org/chromium/components/browser_ui/util/ConversionUtils.java",
     "java/src/org/chromium/components/browser_ui/util/DimensionCompat.java",
diff --git a/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/ChromeItemPickerExtras.java b/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/ChromeItemPickerExtras.java
index 4edac991..0d21b347 100644
--- a/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/ChromeItemPickerExtras.java
+++ b/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/ChromeItemPickerExtras.java
@@ -12,10 +12,6 @@
     // Prevent instantiation
     private ChromeItemPickerExtras() {}
 
-    /** The class name for launching the ChromeItemPickerActivity. */
-    public static final String CHROME_ITEM_PICKER_ACTIVITY_CLASS =
-            "org.chromium.chrome.browser.chrome_item_picker.ChromeItemPickerActivity";
-
     /** Intent extra for the list of tab IDs that should be preselected on startup. */
     public static final String EXTRA_PRESELECTED_TAB_IDS = "EXTRA_PRESELECTED_TAB_IDS";
 
diff --git a/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/ChromeItemPickerUtils.java b/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/ChromeItemPickerUtils.java
new file mode 100644
index 0000000..331fc92
--- /dev/null
+++ b/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/ChromeItemPickerUtils.java
@@ -0,0 +1,35 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.browser_ui.util;
+
+import android.content.Context;
+import android.content.Intent;
+
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
+
+/** Utility class for interacting with the Chrome Item Picker. */
+@NullMarked
+public final class ChromeItemPickerUtils {
+    public static final String ACTIVITY_CLASS_NAME =
+            "org.chromium.chrome.browser.chrome_item_picker.ChromeItemPickerActivity";
+
+    /** Private constructor to prevent instantiation. */
+    private ChromeItemPickerUtils() {}
+
+    /**
+     * Creates an Intent to launch the Chrome Item Picker.
+     *
+     * @param context The context used to create the Intent and set the class name.
+     * @return An intent to launch the Chrome Item Picker or null if it cannot be found.
+     */
+    public static @Nullable Intent createChromeItemPickerIntent(Context context) {
+        try {
+            return new Intent(context, Class.forName(ACTIVITY_CLASS_NAME));
+        } catch (ClassNotFoundException e) {
+            return null;
+        }
+    }
+}
diff --git a/components/contextual_search/contextual_search_service_unittest.cc b/components/contextual_search/contextual_search_service_unittest.cc
index 7397a21..e6876e4 100644
--- a/components/contextual_search/contextual_search_service_unittest.cc
+++ b/components/contextual_search/contextual_search_service_unittest.cc
@@ -446,60 +446,4 @@
   ASSERT_THAT(session_handle->GetController(), NotNull());
 }
 
-TEST_F(ContextualSearchServiceTest, DeleteFile) {
-  auto mock_controller =
-      std::make_unique<MockContextualSearchContextController>();
-  auto metrics_recorder = std::make_unique<ContextualSearchMetricsRecorder>(
-      ContextualSearchSource::kUnknown);
-
-  MockContextualSearchContextController* mock_controller_ptr =
-      mock_controller.get();
-
-  auto session_handle = service_->CreateSessionForTesting(
-      std::move(mock_controller), std::move(metrics_recorder));
-  // Check the search content sharing settings to notify the session handle
-  // that the client is properly checking the pref value.
-  session_handle->CheckSearchContentSharingSettings(&pref_service_);
-
-  // Create a token.
-  base::UnguessableToken token1 = session_handle->CreateContextToken();
-  contextual_search::FileInfo file_info1;
-  file_info1.file_token = token1;
-
-  // Expect controller DeleteFile to be called.
-  EXPECT_CALL(*mock_controller_ptr, GetFileInfo(token1))
-      .WillRepeatedly(testing::Return(&file_info1));
-  EXPECT_CALL(*mock_controller_ptr, DeleteFile(token1))
-      .WillOnce(testing::Return(true));
-
-  // Case 1: Delete uploaded file.
-  // The file has not been submitted yet, so it should be deleted.
-  EXPECT_TRUE(session_handle->DeleteFile(token1));
-
-  // Create another token.
-  base::UnguessableToken token2 = session_handle->CreateContextToken();
-  contextual_search::FileInfo file_info2;
-  file_info2.file_token = token2;
-
-  EXPECT_CALL(*mock_controller_ptr, GetFileInfo(token2))
-      .WillRepeatedly(testing::Return(&file_info2));
-
-  // Submit the token.
-  EXPECT_CALL(*mock_controller_ptr, CreateClientToAimRequest(_))
-      .WillOnce(testing::Invoke(
-          this, &ContextualSearchServiceTest::CaptureClientToAimRequest));
-
-  auto request = std::make_unique<
-      ContextualSearchContextController::CreateClientToAimRequestInfo>();
-  session_handle->CreateClientToAimRequest(std::move(request));
-
-  // Token2 should now be in submitted tokens.
-  // Verify DeleteFile is NOT called on controller.
-  EXPECT_CALL(*mock_controller_ptr, DeleteFile(token2)).Times(0);
-
-  // Case 2: Delete submitted file.
-  // The file has been submitted, so it should NOT be deleted.
-  EXPECT_FALSE(session_handle->DeleteFile(token2));
-}
-
 }  // namespace contextual_search
diff --git a/components/contextual_search/contextual_search_session_handle.cc b/components/contextual_search/contextual_search_session_handle.cc
index b31431b..2fdda67 100644
--- a/components/contextual_search/contextual_search_session_handle.cc
+++ b/components/contextual_search/contextual_search_session_handle.cc
@@ -239,17 +239,6 @@
 
 bool ContextualSearchSessionHandle::DeleteFile(
     const base::UnguessableToken& file_token) {
-  // If the file was already submitted, don't delete it from the context
-  // controller, so that the file info can be looked up in the future.
-  // This prevents the file info for submitted content from being deleted
-  // prematurely, such as when controlling the auto-tab chip for the transition
-  // from the LensOverlay searchbox to the contextual tasks page.
-  if (std::find(submitted_context_tokens_.begin(),
-                submitted_context_tokens_.end(),
-                file_token) != submitted_context_tokens_.end()) {
-    return false;
-  }
-
   // Remove the file token from the list of uploaded context tokens.
   auto it = std::find(uploaded_context_tokens_.begin(),
                       uploaded_context_tokens_.end(), file_token);
diff --git a/components/contextual_search/input_state_model.cc b/components/contextual_search/input_state_model.cc
index a6411e0..f5cb73a 100644
--- a/components/contextual_search/input_state_model.cc
+++ b/components/contextual_search/input_state_model.cc
@@ -99,7 +99,8 @@
     contextual_search::ContextualSearchSessionHandle& session_handle,
     const SearchboxConfig& config,
     bool is_off_the_record)
-    : session_handle_(session_handle), is_off_the_record_(is_off_the_record) {
+    : session_handle_(session_handle.AsWeakPtr()),
+      is_off_the_record_(is_off_the_record) {
   SearchboxConfig mutable_config = config;
   MaybePopulateBrowserTabInputTypeRule(&mutable_config);
 
@@ -185,7 +186,7 @@
 InputStateModel::InputStateModel(
     const InputStateModel& new_input_state_model,
     contextual_search::ContextualSearchSessionHandle& new_session_handle)
-    : session_handle_(new_session_handle),
+    : session_handle_(new_session_handle.AsWeakPtr()),
       is_off_the_record_(new_input_state_model.is_off_the_record_) {
   state_ = new_input_state_model.state_;
   rule_set_ = new_input_state_model.rule_set_;
@@ -252,9 +253,12 @@
 
 // Gets the current input types from the session handle.
 std::vector<omnibox::InputType> GetCurrentInputTypes(
-    const contextual_search::ContextualSearchSessionHandle& session_handle) {
+    const contextual_search::ContextualSearchSessionHandle* session_handle) {
   std::vector<omnibox::InputType> input_types;
-  const auto& uploaded_files = session_handle.GetUploadedContextFileInfos();
+  if (!session_handle) {
+    return input_types;
+  }
+  const auto& uploaded_files = session_handle->GetUploadedContextFileInfos();
   input_types.reserve(uploaded_files.size());
   for (const auto& file_info : uploaded_files) {
     if (file_info.tab_url) {
diff --git a/components/contextual_search/input_state_model.h b/components/contextual_search/input_state_model.h
index 07bbf9c..d32dbf2 100644
--- a/components/contextual_search/input_state_model.h
+++ b/components/contextual_search/input_state_model.h
@@ -94,7 +94,7 @@
 
   InputState state_;
   omnibox::RuleSet rule_set_;
-  base::raw_ref<contextual_search::ContextualSearchSessionHandle>
+  base::WeakPtr<contextual_search::ContextualSearchSessionHandle>
       session_handle_;
   base::RepeatingCallbackList<void(const InputState&)> subscribers_;
 
diff --git a/components/contextual_search/input_state_model_unittest.cc b/components/contextual_search/input_state_model_unittest.cc
index 18ef7b1..f95ad66 100644
--- a/components/contextual_search/input_state_model_unittest.cc
+++ b/components/contextual_search/input_state_model_unittest.cc
@@ -735,4 +735,20 @@
       testing::UnorderedElementsAre(omnibox::ToolMode::TOOL_MODE_DEEP_SEARCH));
 }
 
+// Regression test for crbug.com/487677445. Ensures that the model doesn't crash
+// if it's updated after the session handle has been destroyed.
+TEST_F(InputStateModelTest,
+       Regression_Bug487677445_CrashOnDanglingSessionHandle) {
+  auto local_session = std::make_unique<MockContextualSearchSessionHandle>();
+  omnibox::SearchboxConfig config;
+
+  auto local_model = std::make_unique<InputStateModel>(
+      *local_session, config, /*is_off_the_record=*/false);
+
+  local_session.reset();  // Destroy session.
+
+  // This should not crash.
+  local_model->OnContextChanged();
+}
+
 }  // namespace contextual_search
diff --git a/components/contextual_tasks/internal/contextual_tasks_service_impl.cc b/components/contextual_tasks/internal/contextual_tasks_service_impl.cc
index b367bcf..ea8a325 100644
--- a/components/contextual_tasks/internal/contextual_tasks_service_impl.cc
+++ b/components/contextual_tasks/internal/contextual_tasks_service_impl.cc
@@ -780,7 +780,7 @@
     tasks_.emplace(task.GetTaskId(), task);
   }
   for (auto& observer : observers_) {
-    observer.OnInitialized();
+    observer.OnContextualTasksServiceInitialized();
   }
 }
 
diff --git a/components/contextual_tasks/internal/contextual_tasks_service_impl_unittest.cc b/components/contextual_tasks/internal/contextual_tasks_service_impl_unittest.cc
index 344d8eb..5b908a0 100644
--- a/components/contextual_tasks/internal/contextual_tasks_service_impl_unittest.cc
+++ b/components/contextual_tasks/internal/contextual_tasks_service_impl_unittest.cc
@@ -99,7 +99,7 @@
 
 class MockContextualTasksObserver : public ContextualTasksService::Observer {
  public:
-  MOCK_METHOD(void, OnInitialized, (), (override));
+  MOCK_METHOD(void, OnContextualTasksServiceInitialized, (), (override));
   MOCK_METHOD(void,
               OnTaskAdded,
               (const ContextualTask& task,
@@ -1301,7 +1301,7 @@
   // Wait for the sync pieces to finish init so there aren't multiple code
   // paths trying to add tasks to the service.
   base::RunLoop init_run_loop;
-  EXPECT_CALL(observer_, OnInitialized()).WillOnce([&]() {
+  EXPECT_CALL(observer_, OnContextualTasksServiceInitialized()).WillOnce([&]() {
     init_run_loop.Quit();
   });
   init_run_loop.Run();
@@ -1468,7 +1468,9 @@
   SetContextualTaskSyncBridgeForTesting(std::move(mock_contextual_task_bridge));
 
   base::RunLoop run_loop;
-  EXPECT_CALL(observer_, OnInitialized()).WillOnce([&]() { run_loop.Quit(); });
+  EXPECT_CALL(observer_, OnContextualTasksServiceInitialized()).WillOnce([&]() {
+    run_loop.Quit();
+  });
 
   service_->AddObserver(&observer_);
 
@@ -1518,7 +1520,9 @@
   SetContextualTaskSyncBridgeForTesting(std::move(mock_contextual_task_bridge));
 
   base::RunLoop run_loop;
-  EXPECT_CALL(observer_, OnInitialized()).WillOnce([&]() { run_loop.Quit(); });
+  EXPECT_CALL(observer_, OnContextualTasksServiceInitialized()).WillOnce([&]() {
+    run_loop.Quit();
+  });
 
   service_->AddObserver(&observer_);
 
@@ -1580,7 +1584,9 @@
   SetContextualTaskSyncBridgeForTesting(std::move(mock_contextual_task_bridge));
 
   base::RunLoop run_loop;
-  EXPECT_CALL(observer_, OnInitialized()).WillOnce([&]() { run_loop.Quit(); });
+  EXPECT_CALL(observer_, OnContextualTasksServiceInitialized()).WillOnce([&]() {
+    run_loop.Quit();
+  });
 
   service_->AddObserver(&observer_);
 
diff --git a/components/contextual_tasks/public/contextual_tasks_service.h b/components/contextual_tasks/public/contextual_tasks_service.h
index c9525471..71d43ee 100644
--- a/components/contextual_tasks/public/contextual_tasks_service.h
+++ b/components/contextual_tasks/public/contextual_tasks_service.h
@@ -64,7 +64,7 @@
 
     // The service is initialized and ready to take calls and return stored
     // tasks and threads.
-    virtual void OnInitialized() {}
+    virtual void OnContextualTasksServiceInitialized() {}
 
     // A new task was added at the given |source|.
     virtual void OnTaskAdded(const ContextualTask& task, TriggerSource source) {
diff --git a/components/cross_device/nearby/nearby_features.cc b/components/cross_device/nearby/nearby_features.cc
index a4dd4d5b2..202ffcb 100644
--- a/components/cross_device/nearby/nearby_features.cc
+++ b/components/cross_device/nearby/nearby_features.cc
@@ -28,9 +28,6 @@
 BASE_FEATURE(kEnableNearbyBluetoothClassicScanning,
              base::FEATURE_ENABLED_BY_DEFAULT);
 
-// Enables use of mDNS discovery in Nearby Connections for Nearby Share.
-BASE_FEATURE(kEnableNearbyMdns, base::FEATURE_ENABLED_BY_DEFAULT);
-
 // Enables use of WebRTC in Nearby Connections for Nearby Share.
 BASE_FEATURE(kNearbySharingWebRtc, base::FEATURE_ENABLED_BY_DEFAULT);
 
@@ -56,8 +53,4 @@
   return base::FeatureList::IsEnabled(kEnableNearbyBluetoothClassicScanning);
 }
 
-bool IsNearbyMdnsEnabled() {
-  return base::FeatureList::IsEnabled(kEnableNearbyMdns);
-}
-
 }  // namespace features
diff --git a/components/cross_device/nearby/nearby_features.h b/components/cross_device/nearby/nearby_features.h
index 9b4ee1a..4ea088db 100644
--- a/components/cross_device/nearby/nearby_features.h
+++ b/components/cross_device/nearby/nearby_features.h
@@ -13,12 +13,10 @@
 BASE_DECLARE_FEATURE(kEnableNearbyBleV2ExtendedAdvertising);
 BASE_DECLARE_FEATURE(kEnableNearbyBluetoothClassicAdvertising);
 BASE_DECLARE_FEATURE(kEnableNearbyBluetoothClassicScanning);
-BASE_DECLARE_FEATURE(kEnableNearbyMdns);
 bool IsNearbyBleV2Enabled();
 bool IsNearbyBleV2ExtendedAdvertisingEnabled();
 bool IsNearbyBluetoothClassicAdvertisingEnabled();
 bool IsNearbyBluetoothClassicScanningEnabled();
-bool IsNearbyMdnsEnabled();
 BASE_DECLARE_FEATURE(kNearbySharingWebRtc);
 BASE_DECLARE_FEATURE(kNearbySharingWifiDirect);
 BASE_DECLARE_FEATURE(kNearbySharingWifiLan);
diff --git a/components/enterprise/connectors/core/analysis_service_settings_base.cc b/components/enterprise/connectors/core/analysis_service_settings_base.cc
index e1379db..bbbe912 100644
--- a/components/enterprise/connectors/core/analysis_service_settings_base.cc
+++ b/components/enterprise/connectors/core/analysis_service_settings_base.cc
@@ -55,9 +55,9 @@
   }
 
   service_provider_name_ = *service_provider_name;
-  if (service_provider_config.count(service_provider_name_)) {
-    analysis_config_ =
-        service_provider_config.at(service_provider_name_).analysis;
+  if (auto it = service_provider_config.find(service_provider_name_);
+      it != service_provider_config.end()) {
+    analysis_config_ = it->second.analysis;
   }
   if (!analysis_config_) {
     DLOG(ERROR) << "No analysis config for corresponding service provider";
@@ -323,8 +323,8 @@
 
   std::map<std::string, TagSettings> output;
   for (const std::string& tag : enable_tags) {
-    if (tags_.count(tag)) {
-      output[tag] = tags_.at(tag);
+    if (auto it = tags_.find(tag); it != tags_.end()) {
+      output[tag] = it->second;
     } else {
       output[tag] = TagSettings();
     }
@@ -339,8 +339,8 @@
     const PatternSettings& patterns,
     base::MatcherStringPattern::ID match) {
   // If the pattern exists directly in the map, return its settings.
-  if (patterns.count(match) == 1) {
-    return patterns.at(match);
+  if (auto it = patterns.find(match); it != patterns.end()) {
+    return it->second;
   }
 
   // If the pattern doesn't exist in the map, it might mean that it wasn't the
diff --git a/components/enterprise/connectors/core/cloud_content_scanning/file_analysis_request_base.cc b/components/enterprise/connectors/core/cloud_content_scanning/file_analysis_request_base.cc
index 81a2fb9c..153d302 100644
--- a/components/enterprise/connectors/core/cloud_content_scanning/file_analysis_request_base.cc
+++ b/components/enterprise/connectors/core/cloud_content_scanning/file_analysis_request_base.cc
@@ -426,7 +426,8 @@
       FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
       base::BindOnce(&GetFileDataBlocking, path_,
                      std::move(scoped_file_access_),
-                     cached_data_.mime_type.empty(), is_obfuscated_, true,
+                     cached_data_.mime_type.empty(), is_obfuscated_,
+                     force_sync_hash_computation_,
                      base::OwnedRef(std::move(unused_hash_callback))),
       base::BindOnce(&FileAnalysisRequestBase::OnGotFileData,
                      weakptr_factory_.GetWeakPtr()));
diff --git a/components/input/render_input_router.mojom b/components/input/render_input_router.mojom
index eb9ecc6d..205ed95b7 100644
--- a/components/input/render_input_router.mojom
+++ b/components/input/render_input_router.mojom
@@ -10,6 +10,7 @@
 import "third_party/blink/public/mojom/input/input_event_result.mojom";
 import "third_party/blink/public/mojom/input/input_handler.mojom";
 import "third_party/blink/public/mojom/widget/platform_widget.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
 [EnableIf=is_android]
 import "ui/events/mojom/motion_event_android.mojom";
 
@@ -39,10 +40,10 @@
   // FrameSinkId of root widget which was being touched at the time of transfer.
   viz.mojom.FrameSinkId root_widget_frame_sink_id;
 
-  // Y offset to be added to points received from Android to get coordinates
+  // Offset to be added to points received from Android to get coordinates
   // relative to root widget. This will be used to account for top controls
-  // height when creating MotionEventAndroid on Viz side.
-  float web_contents_y_offset_pix;
+  // height and side UI width when creating MotionEventAndroid on Viz side.
+  gfx.mojom.PointF web_contents_offset;
 
   // Device scale factor being used to create MotionEventAndroid objects for
   // converting device pixels to device independent pixels.
diff --git a/components/network_hints/browser/simple_network_hints_handler_impl.cc b/components/network_hints/browser/simple_network_hints_handler_impl.cc
index 2998f0d..75d8ea1 100644
--- a/components/network_hints/browser/simple_network_hints_handler_impl.cc
+++ b/components/network_hints/browser/simple_network_hints_handler_impl.cc
@@ -165,8 +165,6 @@
       render_frame_host->GetPendingIsolationInfoForSubresources()
           .network_anonymization_key();
 
-  // TODO(crbug.com/447954811): pass the `network_restrictions_id` from the
-  // caller.
   render_frame_host->GetStoragePartition()
       ->GetNetworkContext()
       ->PreconnectSockets(
@@ -174,7 +172,7 @@
           allow_credentials ? network::mojom::CredentialsMode::kInclude
                             : network::mojom::CredentialsMode::kOmit,
           network_anonymization_key,
-          /*network_restrictions_id=*/std::nullopt,
+          render_frame_host->GetNetworkRestrictionsID(),
           net::MutableNetworkTrafficAnnotationTag(),
           /*keepalive_config=*/std::nullopt, mojo::NullRemote());
 }
diff --git a/components/omnibox/browser/mock_aim_eligibility_service.cc b/components/omnibox/browser/mock_aim_eligibility_service.cc
index c725f148..cbb8b03 100644
--- a/components/omnibox/browser/mock_aim_eligibility_service.cc
+++ b/components/omnibox/browser/mock_aim_eligibility_service.cc
@@ -17,6 +17,9 @@
                             url_loader_factory,
                             identity_manager,
                             "en-US",
-                            std::move(configuration)) {}
+                            std::move(configuration)) {
+  ON_CALL(*this, GetSearchboxConfig())
+      .WillByDefault(testing::Return(&mock_config));
+}
 
 MockAimEligibilityService::~MockAimEligibilityService() = default;
diff --git a/components/omnibox/browser/mock_aim_eligibility_service.h b/components/omnibox/browser/mock_aim_eligibility_service.h
index 6bc4065..f88cd1f 100644
--- a/components/omnibox/browser/mock_aim_eligibility_service.h
+++ b/components/omnibox/browser/mock_aim_eligibility_service.h
@@ -37,6 +37,12 @@
               (),
               (const, override));
   MOCK_METHOD(void, FetchEligibility, (RequestSource), (override));
+  MOCK_METHOD(const omnibox::SearchboxConfig*,
+              GetSearchboxConfig,
+              (),
+              (const, override));
+
+  omnibox::SearchboxConfig& config() { return mock_config; }
 
  private:
   // Mock searchbox config object.
diff --git a/components/optimization_guide/internal b/components/optimization_guide/internal
index 946192c..b969c7f 160000
--- a/components/optimization_guide/internal
+++ b/components/optimization_guide/internal
@@ -1 +1 @@
-Subproject commit 946192c2badf817f08319c40ba15addf62565333
+Subproject commit b969c7f54f353cf5679d9290f83a98f5ee609639
diff --git a/components/optimization_guide/proto/BUILD.gn b/components/optimization_guide/proto/BUILD.gn
index d2c23dc..8e49624 100644
--- a/components/optimization_guide/proto/BUILD.gn
+++ b/components/optimization_guide/proto/BUILD.gn
@@ -22,12 +22,14 @@
     "features/actor_login.proto",
     "features/amount_extraction.proto",
     "features/bling_prototyping.proto",
+    "features/classify_api.proto",
     "features/common_quality_data.proto",
     "features/compose.proto",
     "features/contextual_tasks_context.proto",
     "features/default.proto",
     "features/enhanced_calendar.proto",
     "features/example_for_testing.proto",
+    "features/finds.proto",
     "features/forms_classifications.proto",
     "features/gemini_antiscam_protection.proto",
     "features/history_answer.proto",
diff --git a/components/optimization_guide/proto/features/classify_api.proto b/components/optimization_guide/proto/features/classify_api.proto
new file mode 100644
index 0000000..b764cbd
--- /dev/null
+++ b/components/optimization_guide/proto/features/classify_api.proto
@@ -0,0 +1,32 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+edition = "2023";
+
+package optimization_guide.proto;
+
+option optimize_for = LITE_RUNTIME;
+option java_package = "org.chromium.components.optimization_guide.features.proto";
+
+option java_outer_classname = "ClassifyApiProto";
+
+// DO NOT EDIT THIS FILE DIRECTLY!
+//
+// This file is generated in g3 and then synced to Chrome. Instead, please refer to
+// http://go/chrome-mqls-onboarding (Google-internal link), and then changes will
+// be synced with Chrome automatically.
+
+message ClassifyApiLoggingData {
+  ClassifyApiRequest request = 1 [features = { field_presence: EXPLICIT }];
+
+  ClassifyApiResponse response = 2 [features = { field_presence: EXPLICIT }];
+}
+
+message ClassifyApiRequest {
+  string text = 1 [features = { field_presence: EXPLICIT }];
+}
+
+message ClassifyApiResponse {
+  string output = 1 [features = { field_presence: EXPLICIT }];
+}
diff --git a/components/optimization_guide/proto/features/common_quality_data.proto b/components/optimization_guide/proto/features/common_quality_data.proto
index 2b07e8f..a031893 100644
--- a/components/optimization_guide/proto/features/common_quality_data.proto
+++ b/components/optimization_guide/proto/features/common_quality_data.proto
@@ -230,9 +230,12 @@
   // be unique within the browsing session.
   int32 tab_id = 7 [features = { field_presence: EXPLICIT }];
 
-  // A page can only have one popup window open at a time. If one is open, its
-  // details are populated here. The popup window draws on top of the tab and as
-  // such has a higher z order than the main frame's Document.
+  // Provides APC for internal popup widgets created by elements like <select>
+  // and <input type="color"> . Does not provide APC for separate windows opened
+  // via window.open() or similar. A page can only have one popup window open at
+  // a time. If one is open, its details are populated here. The popup window
+  // draws on top of the tab and as such has a higher z order than the main
+  // frame's Document.
   PopupWindow popup_window = 8 [features = { field_presence: EXPLICIT }];
 
   // Information that pertains to the user's profile, not the page.
diff --git a/components/optimization_guide/proto/features/finds.proto b/components/optimization_guide/proto/features/finds.proto
new file mode 100644
index 0000000..b6031e9
--- /dev/null
+++ b/components/optimization_guide/proto/features/finds.proto
@@ -0,0 +1,93 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+edition = "2023";
+
+package optimization_guide.proto;
+
+import "components/optimization_guide/proto/model_quality_metadata.proto";
+
+option optimize_for = LITE_RUNTIME;
+option java_package = "org.chromium.components.optimization_guide.features.proto";
+
+option java_outer_classname = "FindsProto";
+
+// DO NOT EDIT THIS FILE DIRECTLY!
+//
+// This file is generated in g3 and then synced to Chrome. Instead, please refer to
+// http://go/chrome-mqls-onboarding (Google-internal link), and then changes will
+// be synced with Chrome automatically.
+
+// Top-level message required by MES.
+// Next ID: 4
+message FindsLoggingData {
+  FindsSuggestionRequest request = 1 [features = { field_presence: EXPLICIT }];
+
+  FindsSuggestionResponse response = 2 [features = { field_presence: EXPLICIT }];
+
+  ModelExecutionInfo model_execution_info = 3 [features = { field_presence: EXPLICIT }];
+}
+
+// The request for the Chrome Finds feature.
+// Next ID: 2
+message FindsSuggestionRequest {
+  repeated HistoryEntry entries = 1;
+
+  // Encasulates a history entry.
+  message HistoryEntry {
+    int64 visit_time_usec = 1 [features = { field_presence: EXPLICIT }];
+
+    string title = 2 [features = { field_presence: EXPLICIT }];
+
+    string url = 3 [features = { field_presence: EXPLICIT }];
+  }
+}
+
+// The response for the Chrome Finds feature.
+// Next ID: 2
+message FindsSuggestionResponse {
+  repeated SuggestionTheme suggestions = 1;
+
+  // A grouped collection of suggestions around a central topic,
+  // there can be multiple of these per-request.
+  message SuggestionTheme {
+    // The "hook" title for the notification (e.g., "Best Mexican in NYC").
+    string theme_title = 1 [features = { field_presence: EXPLICIT }];
+
+    // Identifies the theme by a specific type, used for user opt-out.
+    ThemeType theme_type = 2 [features = { field_presence: EXPLICIT }];
+
+    // The list of net-new URLs matching this theme.
+    repeated SuggestedContent suggestions = 3;
+
+    // Score used to prioritize client behavior.
+    int64 score = 4 [features = { field_presence: EXPLICIT }];
+
+    // A single entry for suggested content, there can be multiple of
+    //  these per-theme.
+    message SuggestedContent {
+      // The title to display in the notification.
+      string title = 1 [features = { field_presence: EXPLICIT }];
+
+      // The destination URL.
+      // Must be validated as "live" (200 OK) before showing.
+      string target_url = 2 [features = { field_presence: EXPLICIT }];
+    }
+
+    // Bucket themes to support "opting-out" of topics on the client.
+    enum ThemeType {
+      UNKNOWN = 0;
+
+      EVENTS_AND_ACTIVITIES = 1;
+
+      FOOD_AND_DINING = 2;
+
+      ENTERTAINMENT = 3;
+
+      SHOPPING = 4;
+
+      TRAVEL = 5;
+    }
+  }
+}
diff --git a/components/optimization_guide/proto/model_quality_service.proto b/components/optimization_guide/proto/model_quality_service.proto
index e0217f04..e47fe14 100644
--- a/components/optimization_guide/proto/model_quality_service.proto
+++ b/components/optimization_guide/proto/model_quality_service.proto
@@ -9,10 +9,12 @@
 import "components/optimization_guide/proto/features/actor_login.proto";
 import "components/optimization_guide/proto/features/amount_extraction.proto";
 import "components/optimization_guide/proto/features/bling_prototyping.proto";
+import "components/optimization_guide/proto/features/classify_api.proto";
 import "components/optimization_guide/proto/features/compose.proto";
 import "components/optimization_guide/proto/features/contextual_tasks_context.proto";
 import "components/optimization_guide/proto/features/default.proto";
 import "components/optimization_guide/proto/features/enhanced_calendar.proto";
+import "components/optimization_guide/proto/features/finds.proto";
 import "components/optimization_guide/proto/features/forms_classifications.proto";
 import "components/optimization_guide/proto/features/gemini_antiscam_protection.proto";
 import "components/optimization_guide/proto/features/history_answer.proto";
@@ -109,6 +111,10 @@
 
     GeminiAntiscamProtectionLoggingData gemini_antiscam_protection = 34;
 
+    ClassifyApiLoggingData classify_api = 35;
+
+    FindsLoggingData finds = 36;
+
     DefaultLoggingData default = 1000;
   }
 }
diff --git a/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.cc b/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.cc
index 9d93ee9..fa63124 100644
--- a/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.cc
+++ b/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.cc
@@ -78,15 +78,6 @@
       merged_candidate.ImageLoadEnd());
 }
 
-void Reset(ContentfulPaintTimingInfo& timing) {
-  timing.Reset(std::nullopt, 0u, blink::LargestContentfulPaintType::kNone,
-               /*image_bpp=*/0.0,
-               /*image_request_priority=*/std::nullopt,
-               /*image_discovery_time=*/std::nullopt,
-               /*image_load_start=*/std::nullopt,
-               /*image_load_end=*/std::nullopt);
-}
-
 bool IsSameSite(const GURL& url1, const GURL& url2) {
   // We can't use SiteInstance::IsSameSiteWithURL() because both mainframe and
   // subframe are under default SiteInstance on low-end Android environment, and
@@ -206,6 +197,15 @@
   image_load_end_ = image_load_end;
 }
 
+void ContentfulPaintTimingInfo::Clear() {
+  Reset(std::nullopt, 0u, blink::LargestContentfulPaintType::kNone,
+        /*image_bpp=*/0.0,
+        /*image_request_priority=*/std::nullopt,
+        /*image_discovery_time=*/std::nullopt,
+        /*image_load_start=*/std::nullopt,
+        /*image_load_end=*/std::nullopt);
+}
+
 ContentfulPaint::ContentfulPaint(bool in_main_frame,
                                  blink::LargestContentfulPaintType type)
     : text_(ContentfulPaintTimingInfo::LargestContentTextOrImage::kText,
@@ -220,6 +220,11 @@
   return MergeTimingsBySizeAndTime(text_, image_);
 }
 
+void ContentfulPaint::Clear() {
+  Text().Clear();
+  Image().Clear();
+}
+
 // static
 bool LargestContentfulPaintHandler::AssignTimeAndSizeForLargestContentfulPaint(
     const page_load_metrics::mojom::LargestContentfulPaintTiming&
@@ -412,17 +417,17 @@
     // consistently the case when a click on the main frame produces a new
     // iframe which contains the largest content so far.
     if (!IsValid(main_frame_contentful_paint_.Text().Time()))
-      Reset(main_frame_contentful_paint_.Text());
+      main_frame_contentful_paint_.Text().Clear();
     if (!IsValid(main_frame_contentful_paint_.Image().Time()))
-      Reset(main_frame_contentful_paint_.Image());
+      main_frame_contentful_paint_.Image().Clear();
     if (!IsValid(subframe_contentful_paint_.Text().Time()))
-      Reset(subframe_contentful_paint_.Text());
+      subframe_contentful_paint_.Text().Clear();
     if (!IsValid(subframe_contentful_paint_.Image().Time()))
-      Reset(subframe_contentful_paint_.Image());
+      subframe_contentful_paint_.Image().Clear();
     if (!IsValid(cross_site_subframe_contentful_paint_.Text().Time()))
-      Reset(cross_site_subframe_contentful_paint_.Text());
+      cross_site_subframe_contentful_paint_.Text().Clear();
     if (!IsValid(cross_site_subframe_contentful_paint_.Image().Time()))
-      Reset(cross_site_subframe_contentful_paint_.Image());
+      cross_site_subframe_contentful_paint_.Image().Clear();
   }
 }
 
diff --git a/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h b/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h
index 1e8ca9b..d2e40b2 100644
--- a/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h
+++ b/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h
@@ -99,6 +99,8 @@
 
   std::unique_ptr<base::trace_event::TracedValue> DataAsTraceValue() const;
 
+  void Clear();
+
   ContentfulPaintTimingInfo() = delete;
 
  private:
@@ -126,6 +128,8 @@
   const ContentfulPaintTimingInfo& Image() const { return image_; }
   const ContentfulPaintTimingInfo& MergeTextAndImageTiming() const;
 
+  void Clear();
+
  private:
   ContentfulPaintTimingInfo text_;
   ContentfulPaintTimingInfo image_;
diff --git a/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc b/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc
index 41e8060..bec04fd 100644
--- a/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc
+++ b/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc
@@ -548,20 +548,7 @@
 
 void PageLoadMetricsUpdateDispatcher::
     ClearSoftNavigationLargestContentfulPaint() {
-  soft_navigation_contentful_paint_candidate_.Text().Reset(
-      std::nullopt, 0u, blink::LargestContentfulPaintType::kNone,
-      /*image_bpp=*/0.0,
-      /*image_request_priority=*/std::nullopt,
-      /*image_discovery_time=*/std::nullopt,
-      /*image_load_start=*/std::nullopt,
-      /*image_load_end=*/std::nullopt);
-  soft_navigation_contentful_paint_candidate_.Image().Reset(
-      std::nullopt, 0u, blink::LargestContentfulPaintType::kNone,
-      /*image_bpp=*/0.0,
-      /*image_request_priority=*/std::nullopt,
-      /*image_discovery_time=*/std::nullopt,
-      /*image_load_start=*/std::nullopt,
-      /*image_load_end=*/std::nullopt);
+  soft_navigation_contentful_paint_candidate_.Clear();
 }
 
 void PageLoadMetricsUpdateDispatcher::SetUpSharedMemoryForDroppedFrames(
diff --git a/components/private_ai/BUILD.gn b/components/private_ai/BUILD.gn
index 608ad5e..c0f60d8f8 100644
--- a/components/private_ai/BUILD.gn
+++ b/components/private_ai/BUILD.gn
@@ -102,8 +102,6 @@
   sources = [
     "testing/fake_connection.cc",
     "testing/fake_connection.h",
-    "testing/fake_secure_channel.cc",
-    "testing/fake_secure_channel.h",
     "testing/fake_token_manager.cc",
     "testing/fake_token_manager.h",
     "testing/mock_private_ai_client.h",
@@ -112,7 +110,6 @@
     ":private_ai",
     ":proto",
     "//base",
-    "//base/test:test_support",
     "//components/private_ai/phosphor",
     "//testing/gmock",
   ]
@@ -121,7 +118,6 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
-    "client_impl_integration_test.cc",
     "client_impl_unittest.cc",
     "connection_basic_unittest.cc",
     "connection_metrics_unittest.cc",
diff --git a/components/private_ai/client_impl_integration_test.cc b/components/private_ai/client_impl_integration_test.cc
deleted file mode 100644
index fa7c762..0000000
--- a/components/private_ai/client_impl_integration_test.cc
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright 2026 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/functional/bind.h"
-#include "base/functional/callback.h"
-#include "base/memory/raw_ptr.h"
-#include "base/run_loop.h"
-#include "base/test/gmock_callback_support.h"
-#include "base/test/task_environment.h"
-#include "base/test/test_future.h"
-#include "base/types/expected.h"
-#include "components/private_ai/client_impl.h"
-#include "components/private_ai/common/private_ai_logger.h"
-#include "components/private_ai/connection_basic.h"
-#include "components/private_ai/connection_metrics.h"
-#include "components/private_ai/connection_timeout.h"
-#include "components/private_ai/connection_token_attestation.h"
-#include "components/private_ai/error_code.h"
-#include "components/private_ai/private_ai_common.h"
-#include "components/private_ai/proto/private_ai.pb.h"
-#include "components/private_ai/secure_channel.h"
-#include "components/private_ai/testing/fake_secure_channel.h"
-#include "components/private_ai/testing/fake_token_manager.h"
-#include "services/network/test/test_network_context.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace private_ai {
-
-namespace {
-
-using ::testing::_;
-using ::testing::Invoke;
-
-class IntegrationConnectionFactory : public ConnectionFactory {
- public:
-  IntegrationConnectionFactory(
-      FakeSecureChannelFactory::OnCreatedCallback on_secure_channel_created,
-      FakeSecureChannelFactory::OnDestroyedCallback on_secure_channel_destroyed,
-      FakeTokenManager* token_manager,
-      PrivateAiLogger* logger)
-      : on_secure_channel_created_(std::move(on_secure_channel_created)),
-        on_secure_channel_destroyed_(std::move(on_secure_channel_destroyed)),
-        token_manager_(token_manager),
-        logger_(logger) {}
-
-  std::unique_ptr<Connection> Create(
-      base::OnceCallback<void(ErrorCode)> on_disconnect) override {
-    auto split_on_disconnect =
-        base::SplitOnceCallback(std::move(on_disconnect));
-
-    auto secure_channel_factory = std::make_unique<FakeSecureChannelFactory>(
-        on_secure_channel_created_, on_secure_channel_destroyed_);
-
-    std::unique_ptr<Connection> connection =
-        std::make_unique<ConnectionBasic>(std::move(secure_channel_factory),
-                                          std::move(split_on_disconnect.first));
-
-    connection = std::make_unique<ConnectionMetrics>(std::move(connection));
-
-    connection = std::make_unique<ConnectionTimeout>(std::move(connection));
-
-    connection = std::make_unique<ConnectionTokenAttestation>(
-        std::move(connection), token_manager_, logger_,
-        std::move(split_on_disconnect.second));
-    token_manager_->WaitForPendingCallback();
-    return connection;
-  }
-
- private:
-  FakeSecureChannelFactory::OnCreatedCallback on_secure_channel_created_;
-  FakeSecureChannelFactory::OnDestroyedCallback on_secure_channel_destroyed_;
-  raw_ptr<FakeTokenManager> token_manager_;
-  raw_ptr<PrivateAiLogger> logger_;
-};
-
-}  // namespace
-
-class ClientImplIntegrationTest : public testing::Test {
- public:
-  void SetUp() override {
-    auto logger = std::make_unique<PrivateAiLogger>();
-    PrivateAiLogger* logger_ptr = logger.get();
-    auto factory = std::make_unique<IntegrationConnectionFactory>(
-        base::BindRepeating(
-            &ClientImplIntegrationTest::on_secure_channel_created,
-            base::Unretained(this)),
-        base::BindRepeating(
-            &ClientImplIntegrationTest::on_secure_channel_destroyed,
-            base::Unretained(this)),
-        &token_manager_, logger_ptr);
-
-    client_ =
-        std::make_unique<ClientImpl>(std::move(factory), std::move(logger));
-  }
-
-  void on_secure_channel_created(FakeSecureChannel* secure_channel) {
-    secure_channels_.push_back(secure_channel);
-  }
-
-  void on_secure_channel_destroyed(FakeSecureChannel* secure_channel) {
-    std::erase(secure_channels_, secure_channel);
-  }
-
-  FakeSecureChannel* last_secure_channel() {
-    if (secure_channels_.empty()) {
-      return nullptr;
-    }
-    return secure_channels_.back();
-  }
-
- protected:
-  base::test::TaskEnvironment task_environment_{
-      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
-
-  FakeTokenManager token_manager_;
-  std::unique_ptr<ClientImpl> client_;
-  std::vector<raw_ptr<FakeSecureChannel>> secure_channels_;
-};
-
-TEST_F(ClientImplIntegrationTest, FullStackSuccess) {
-  base::test::TestFuture<base::expected<std::string, ErrorCode>> future;
-  client_->SendTextRequest(proto::FeatureName::FEATURE_NAME_UNSPECIFIED,
-                           "hello", future.GetCallback(), /*options=*/{});
-
-  // 1. Attestation starts. FakeTokenManager gets a request.
-  EXPECT_EQ(token_manager_.GetPendingCallbackCount(), 1u);
-  token_manager_.RunPendingCallbacks();
-
-  // 2. SecureChannel (Basic) is created and gets the attestation request.
-  auto* channel = last_secure_channel();
-  ASSERT_TRUE(channel);
-  EXPECT_TRUE(channel->last_written_request().has_anonymous_token_request());
-
-  // 3. Respond to attestation.
-  proto::PrivateAiResponse attestation_response;
-  attestation_response.set_request_id(
-      channel->last_written_request().request_id());
-  channel->send_back_response(attestation_response);
-
-  // 4. Now the original text request should be sent.
-  EXPECT_TRUE(channel->last_written_request().has_generate_content_request());
-
-  // 5. Respond to text request.
-  proto::PrivateAiResponse text_response;
-  text_response.set_request_id(channel->last_written_request().request_id());
-  text_response.mutable_generate_content_response()
-      ->add_candidates()
-      ->mutable_content()
-      ->add_parts()
-      ->set_text("world");
-  channel->send_back_response(text_response);
-
-  // 6. Verify final result.
-  auto result = future.Get();
-  ASSERT_TRUE(result.has_value());
-  EXPECT_EQ(result.value(), "world");
-}
-
-TEST_F(ClientImplIntegrationTest, AttestationFailure) {
-  base::test::TestFuture<base::expected<std::string, ErrorCode>> future;
-  client_->SendTextRequest(proto::FeatureName::FEATURE_NAME_UNSPECIFIED,
-                           "hello", future.GetCallback(), /*options=*/{});
-
-  // 1. Attestation starts.
-  EXPECT_EQ(token_manager_.GetPendingCallbackCount(), 1u);
-  // Simulate token fetch failure.
-  token_manager_.RespondToGetAuthToken(std::nullopt);
-
-  // 2. Client should receive an error.
-  auto result = future.Get();
-  ASSERT_FALSE(result.has_value());
-  EXPECT_EQ(result.error(), ErrorCode::kClientAttestationFailed);
-}
-
-TEST_F(ClientImplIntegrationTest, Timeout) {
-  base::test::TestFuture<base::expected<std::string, ErrorCode>> future;
-  client_->SendTextRequest(proto::FeatureName::FEATURE_NAME_UNSPECIFIED,
-                           "hello", future.GetCallback(),
-                           {.timeout = base::Seconds(5)});
-
-  // Complete attestation successfully.
-  token_manager_.RunPendingCallbacks();
-  auto* channel = last_secure_channel();
-  ASSERT_TRUE(channel);
-  proto::PrivateAiResponse attestation_response;
-  attestation_response.set_request_id(
-      channel->last_written_request().request_id());
-  channel->send_back_response(attestation_response);
-
-  // Text request is sent.
-  EXPECT_TRUE(channel->last_written_request().has_generate_content_request());
-
-  // Wait for timeout.
-  task_environment_.FastForwardBy(base::Seconds(6));
-
-  // Verify timeout error.
-  auto result = future.Get();
-  ASSERT_FALSE(result.has_value());
-  EXPECT_EQ(result.error(), ErrorCode::kTimeout);
-}
-
-TEST_F(ClientImplIntegrationTest, ConcurrentRequestsDuringAttestation) {
-  base::test::TestFuture<base::expected<std::string, ErrorCode>> future1;
-  base::test::TestFuture<base::expected<std::string, ErrorCode>> future2;
-
-  client_->SendTextRequest(proto::FeatureName::FEATURE_NAME_UNSPECIFIED,
-                           "request1", future1.GetCallback(), /*options=*/{});
-  client_->SendTextRequest(proto::FeatureName::FEATURE_NAME_UNSPECIFIED,
-                           "request2", future2.GetCallback(), /*options=*/{});
-
-  // 1. Attestation starts (only one token fetch should be triggered).
-  EXPECT_EQ(token_manager_.GetPendingCallbackCount(), 1u);
-  token_manager_.RunPendingCallbacks();
-
-  auto* channel = last_secure_channel();
-  ASSERT_TRUE(channel);
-
-  // 2. Complete attestation.
-  proto::PrivateAiResponse attestation_response;
-  attestation_response.set_request_id(
-      channel->last_written_request().request_id());
-  channel->send_back_response(attestation_response);
-
-  // 3. Now both requests should be sent.
-  ASSERT_EQ(channel->written_requests().size(), 3u);
-
-  // Handle request 1
-  EXPECT_EQ(channel->written_requests()[1]
-                .generate_content_request()
-                .contents(0)
-                .parts(0)
-                .text(),
-            "request1");
-  int32_t id1 = channel->written_requests()[1].request_id();
-  proto::PrivateAiResponse resp1;
-  resp1.set_request_id(id1);
-  resp1.mutable_generate_content_response()
-      ->add_candidates()
-      ->mutable_content()
-      ->add_parts()
-      ->set_text("response1");
-  channel->send_back_response(resp1);
-
-  // Handle request 2
-  EXPECT_EQ(channel->written_requests()[2]
-                .generate_content_request()
-                .contents(0)
-                .parts(0)
-                .text(),
-            "request2");
-  int32_t id2 = channel->written_requests()[2].request_id();
-  proto::PrivateAiResponse resp2;
-  resp2.set_request_id(id2);
-  resp2.mutable_generate_content_response()
-      ->add_candidates()
-      ->mutable_content()
-      ->add_parts()
-      ->set_text("response2");
-  channel->send_back_response(resp2);
-
-  // 4. Verify both results.
-  EXPECT_EQ(future1.Get().value(), "response1");
-  EXPECT_EQ(future2.Get().value(), "response2");
-}
-
-TEST_F(ClientImplIntegrationTest, DisconnectDuringAttestation) {
-  base::test::TestFuture<base::expected<std::string, ErrorCode>> future;
-  client_->SendTextRequest(proto::FeatureName::FEATURE_NAME_UNSPECIFIED,
-                           "hello", future.GetCallback(), /*options=*/{});
-
-  // 1. Attestation starts.
-  token_manager_.RunPendingCallbacks();
-  auto* channel = last_secure_channel();
-  ASSERT_TRUE(channel);
-
-  // 2. Simulate channel disconnect before responding to attestation.
-  channel->send_back_error(ErrorCode::kNetworkError);
-
-  // 3. The original request should fail with the disconnect error.
-  ASSERT_TRUE(future.IsReady());
-  auto result = future.Get();
-  ASSERT_FALSE(result.has_value());
-  EXPECT_EQ(result.error(), ErrorCode::kNetworkError);
-}
-
-TEST_F(ClientImplIntegrationTest, ClientDestroyedDuringAttestation) {
-  base::test::TestFuture<base::expected<std::string, ErrorCode>> future;
-  client_->SendTextRequest(proto::FeatureName::FEATURE_NAME_UNSPECIFIED,
-                           "hello", future.GetCallback(), /*options=*/{});
-
-  // 1. Attestation starts.
-  token_manager_.RunPendingCallbacks();
-
-  // 2. Destroy the client while attestation is pending.
-  client_.reset();
-
-  // 3. The request should be resolved with kDestroyed.
-  ASSERT_TRUE(future.IsReady());
-  auto result = future.Get();
-  ASSERT_FALSE(result.has_value());
-  EXPECT_EQ(result.error(), ErrorCode::kDestroyed);
-}
-
-TEST_F(ClientImplIntegrationTest, AttestationTimedOut) {
-  base::test::TestFuture<base::expected<std::string, ErrorCode>> future;
-  client_->SendTextRequest(proto::FeatureName::FEATURE_NAME_UNSPECIFIED,
-                           "hello", future.GetCallback(),
-                           {.timeout = base::Seconds(5)});
-
-  // 1. Attestation starts.
-  token_manager_.RunPendingCallbacks();
-  auto* channel = last_secure_channel();
-  ASSERT_TRUE(channel);
-
-  // 2. Wait for the attestation timeout (60 seconds).
-  task_environment_.FastForwardBy(base::Seconds(61));
-
-  // 3. Result should be kClientAttestationFailed because
-  // ConnectionTokenAttestation converts any error during attestation response
-  // to kClientAttestationFailed.
-  ASSERT_TRUE(future.IsReady());
-  auto result = future.Get();
-  ASSERT_FALSE(result.has_value());
-  EXPECT_EQ(result.error(), ErrorCode::kClientAttestationFailed);
-}
-
-}  // namespace private_ai
diff --git a/components/private_ai/connection.h b/components/private_ai/connection.h
index 811edf7..77371056 100644
--- a/components/private_ai/connection.h
+++ b/components/private_ai/connection.h
@@ -38,8 +38,7 @@
                     OnRequestCallback callback) = 0;
 
   // Invoked when the connection is being destroyed. Implementations should
-  // resolve all pending requests with `error`, call OnDestroy() on the inner
-  // connection, reset all un-owned pointers and invalidate weakptrs.
+  // resolve all pending requests with `error`.
   virtual void OnDestroy(ErrorCode error) = 0;
 };
 
diff --git a/components/private_ai/connection_basic.cc b/components/private_ai/connection_basic.cc
index f6d5204b..9321855 100644
--- a/components/private_ai/connection_basic.cc
+++ b/components/private_ai/connection_basic.cc
@@ -56,13 +56,10 @@
 }
 
 void ConnectionBasic::OnDestroy(ErrorCode error) {
-  on_disconnect_.Reset();
   auto pending_requests = std::move(pending_request_callbacks_);
   for (auto& pending_request : pending_requests) {
     std::move(pending_request.second).Run(base::unexpected(error));
   }
-
-  weak_factory_.InvalidateWeakPtrsAndDoom();
 }
 
 void ConnectionBasic::OnResponseReceived(
diff --git a/components/private_ai/connection_basic.h b/components/private_ai/connection_basic.h
index edf080f..ac24f80e 100644
--- a/components/private_ai/connection_basic.h
+++ b/components/private_ai/connection_basic.h
@@ -53,7 +53,6 @@
 
   std::unique_ptr<SecureChannel> secure_channel_;
 
-  // Called to trigger a disconnect and destruction of the connection.
   base::OnceCallback<void(ErrorCode)> on_disconnect_;
 
   int32_t next_request_id_{1};
diff --git a/components/private_ai/connection_basic_unittest.cc b/components/private_ai/connection_basic_unittest.cc
index b7a456e..e43a500 100644
--- a/components/private_ai/connection_basic_unittest.cc
+++ b/components/private_ai/connection_basic_unittest.cc
@@ -18,7 +18,6 @@
 #include "components/private_ai/private_ai_common.h"
 #include "components/private_ai/proto/private_ai.pb.h"
 #include "components/private_ai/secure_channel.h"
-#include "components/private_ai/testing/fake_secure_channel.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -29,16 +28,78 @@
 using ::testing::_;
 using ::testing::Invoke;
 
+class FakeSecureChannel : public SecureChannel {
+ public:
+  explicit FakeSecureChannel(ResponseCallback callback)
+      : response_callback_(std::move(callback)) {
+    CHECK(response_callback_);
+  }
+
+  ~FakeSecureChannel() override = default;
+
+  bool Write(const Request& request) override {
+    // Make sure that `request` is encoded `proto::PrivateAiRequest` proto
+    // struct.
+    proto::PrivateAiRequest request_proto;
+    CHECK(request_proto.ParseFromArray(request.data(), request.size()));
+    last_written_request_ = request_proto;
+
+    return write_succeeds_;
+  }
+
+  // Test control methods:
+  void set_write_succeeds(bool succeeds) { write_succeeds_ = succeeds; }
+
+  const proto::PrivateAiRequest& last_written_request() const {
+    return last_written_request_;
+  }
+  void send_back_response(const proto::PrivateAiResponse& response) {
+    std::vector<uint8_t> response_bytes(response.ByteSizeLong());
+    response.SerializeToArray(response_bytes.data(), response_bytes.size());
+
+    CHECK(response_callback_);
+    response_callback_.Run(std::move(response_bytes));
+  }
+
+  void send_back_error(ErrorCode error) {
+    CHECK(response_callback_);
+    response_callback_.Run(base::unexpected(error));
+  }
+
+ private:
+  ResponseCallback response_callback_;
+  proto::PrivateAiRequest last_written_request_;
+  bool write_succeeds_ = true;
+};
+
+class FakeSecureChannelFactory : public SecureChannel::Factory {
+ public:
+  using OnCreatedCallback = base::RepeatingCallback<void(FakeSecureChannel*)>;
+
+  explicit FakeSecureChannelFactory(OnCreatedCallback on_created_callback)
+      : on_created_callback_(std::move(on_created_callback)) {}
+
+  ~FakeSecureChannelFactory() override = default;
+
+  std::unique_ptr<SecureChannel> Create(
+      SecureChannel::ResponseCallback callback) override {
+    auto secure_channel =
+        std::make_unique<FakeSecureChannel>(std::move(callback));
+    on_created_callback_.Run(secure_channel.get());
+    return secure_channel;
+  }
+
+ private:
+  OnCreatedCallback on_created_callback_;
+};
+
 class ConnectionBasicTest : public testing::Test {
  public:
   void SetUp() override {
     connection_ = std::make_unique<ConnectionBasic>(
         std::make_unique<FakeSecureChannelFactory>(
             base::BindRepeating(&ConnectionBasicTest::on_secure_channel_created,
-                                base::Unretained(this)),
-            base::BindRepeating(
-                &ConnectionBasicTest::on_secure_channel_destroyed,
-                base::Unretained(this))),
+                                base::Unretained(this))),
         base::BindOnce(&ConnectionBasicTest::on_disconnect,
                        base::Unretained(this)));
 
@@ -50,12 +111,6 @@
     secure_channel_ = secure_channel;
   }
 
-  void on_secure_channel_destroyed(FakeSecureChannel* secure_channel) {
-    if (secure_channel_ == secure_channel) {
-      secure_channel_ = nullptr;
-    }
-  }
-
   void on_disconnect(ErrorCode error_code) {
     on_disconnect_counter_++;
     connection_->OnDestroy(error_code);
diff --git a/components/private_ai/connection_metrics.cc b/components/private_ai/connection_metrics.cc
index 8094f6e..e7d3377 100644
--- a/components/private_ai/connection_metrics.cc
+++ b/components/private_ai/connection_metrics.cc
@@ -38,8 +38,6 @@
 
 void ConnectionMetrics::OnDestroy(ErrorCode error) {
   inner_connection_->OnDestroy(error);
-
-  weak_factory_.InvalidateWeakPtrsAndDoom();
 }
 
 void ConnectionMetrics::OnResponse(
diff --git a/components/private_ai/connection_proxy.cc b/components/private_ai/connection_proxy.cc
index 38fb6eb..615d957d 100644
--- a/components/private_ai/connection_proxy.cc
+++ b/components/private_ai/connection_proxy.cc
@@ -92,8 +92,6 @@
 }
 
 void ConnectionProxy::OnDestroy(ErrorCode error) {
-  on_disconnect_.Reset();
-
   auto pending_requests = std::move(pending_requests_);
   for (auto& pending : pending_requests) {
     std::move(pending.callback).Run(base::unexpected(error));
@@ -102,10 +100,6 @@
   if (inner_connection_) {
     inner_connection_->OnDestroy(error);
   }
-
-  token_manager_ = nullptr;
-  network_service_ = nullptr;
-  weak_factory_.InvalidateWeakPtrsAndDoom();
 }
 
 void ConnectionProxy::CallOnDisconnect(ErrorCode error_code) {
diff --git a/components/private_ai/connection_proxy.h b/components/private_ai/connection_proxy.h
index 5d7b1089..4450873 100644
--- a/components/private_ai/connection_proxy.h
+++ b/components/private_ai/connection_proxy.h
@@ -81,8 +81,6 @@
   raw_ptr<phosphor::TokenManager> token_manager_;
   raw_ptr<network::mojom::NetworkService> network_service_;
   InnerConnectionFactory inner_connection_factory_;
-
-  // Called to trigger a disconnect and destruction of the connection.
   base::OnceCallback<void(ErrorCode)> on_disconnect_;
 
   mojo::Remote<network::mojom::NetworkContext> proxied_context_;
diff --git a/components/private_ai/connection_timeout.cc b/components/private_ai/connection_timeout.cc
index e437a9657..cc9f3de 100644
--- a/components/private_ai/connection_timeout.cc
+++ b/components/private_ai/connection_timeout.cc
@@ -49,10 +49,7 @@
   for (auto& entry : pending) {
     std::move(entry.second).Run(base::unexpected(error));
   }
-
   inner_connection_->OnDestroy(error);
-
-  weak_factory_.InvalidateWeakPtrsAndDoom();
 }
 
 void ConnectionTimeout::OnResponse(
diff --git a/components/private_ai/connection_token_attestation.cc b/components/private_ai/connection_token_attestation.cc
index 24d04e0..610a5e6 100644
--- a/components/private_ai/connection_token_attestation.cc
+++ b/components/private_ai/connection_token_attestation.cc
@@ -13,7 +13,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/task/sequenced_task_runner.h"
 #include "components/private_ai/common/private_ai_logger.h"
 #include "components/private_ai/phosphor/token_manager.h"
 #include "components/private_ai/proto/private_ai.pb.h"
@@ -51,11 +50,8 @@
   CHECK(logger_);
   CHECK(on_disconnect_);
 
-  // Sending attestation request asynchronously to avoid failures
-  // during construction of this object.
-  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE, base::BindOnce(&ConnectionTokenAttestation::FetchToken,
-                                weak_factory_.GetWeakPtr()));
+  // Sending attestation request as soon as possible.
+  FetchToken();
 }
 
 ConnectionTokenAttestation::~ConnectionTokenAttestation() = default;
@@ -131,7 +127,6 @@
 
 void ConnectionTokenAttestation::OnDestroy(ErrorCode error) {
   attestation_state_ = AttestationState::kFailed;
-  on_disconnect_.Reset();
 
   auto pending_requests = std::move(pending_requests_);
   for (auto& pending_request : pending_requests) {
@@ -139,10 +134,6 @@
   }
 
   inner_connection_->OnDestroy(error);
-
-  token_manager_ = nullptr;
-  logger_ = nullptr;
-  weak_factory_.InvalidateWeakPtrsAndDoom();
 }
 
 void ConnectionTokenAttestation::CallOnDisconnect(ErrorCode error_code) {
diff --git a/components/private_ai/connection_token_attestation.h b/components/private_ai/connection_token_attestation.h
index 4b504030..bce31ea 100644
--- a/components/private_ai/connection_token_attestation.h
+++ b/components/private_ai/connection_token_attestation.h
@@ -77,10 +77,8 @@
   void CallOnDisconnect(ErrorCode error_code);
 
   const std::unique_ptr<Connection> inner_connection_;
-  raw_ptr<phosphor::TokenManager> token_manager_;
-  raw_ptr<PrivateAiLogger> logger_;
-
-  // Called to trigger a disconnect and destruction of the connection.
+  const raw_ptr<phosphor::TokenManager> token_manager_;
+  const raw_ptr<PrivateAiLogger> logger_;
   base::OnceCallback<void(ErrorCode)> on_disconnect_;
 
   AttestationState attestation_state_ = AttestationState::kFetchingToken;
diff --git a/components/private_ai/connection_token_attestation_unittest.cc b/components/private_ai/connection_token_attestation_unittest.cc
index b08988d..9db43585 100644
--- a/components/private_ai/connection_token_attestation_unittest.cc
+++ b/components/private_ai/connection_token_attestation_unittest.cc
@@ -34,7 +34,6 @@
         std::move(fake_connection), &token_manager_, &logger_,
         base::BindOnce(&ConnectionTokenAttestationTest::OnDisconnect,
                        base::Unretained(this)));
-    token_manager_.WaitForPendingCallback();
   }
 
   void OnDisconnect(ErrorCode error_code) {
diff --git a/components/private_ai/proto/private_ai.proto b/components/private_ai/proto/private_ai.proto
index cf2647f..67eb78a7 100644
--- a/components/private_ai/proto/private_ai.proto
+++ b/components/private_ai/proto/private_ai.proto
@@ -49,8 +49,9 @@
   FEATURE_NAME_UNSPECIFIED = 0;
   FEATURE_NAME_DEMO_GEMINI_GENERATE_CONTENT = 3;
   FEATURE_NAME_CHROME_ZERO_STATE_SUGGESTION = 700;
+  FEATURE_NAME_CHROME_FORMS_AI = 701;
 }
-// LINT.ThenChange(//tools/metrics/histograms/enums.xml:LegionFeatureName)
+// LINT.ThenChange(//tools/metrics/histograms/enums.xml:PrivateAiFeatureName)
 
 message PaicMessage {
   FeatureName feature_name = 1;
diff --git a/components/private_ai/testing/fake_connection.cc b/components/private_ai/testing/fake_connection.cc
index cf44ef4..f34f5dd 100644
--- a/components/private_ai/testing/fake_connection.cc
+++ b/components/private_ai/testing/fake_connection.cc
@@ -48,7 +48,6 @@
 }
 
 void FakeConnection::OnDestroy(ErrorCode error) {
-  on_disconnect_.Reset();
   auto callbacks = std::move(pending_requests_);
   for (auto& pending_request : callbacks) {
     std::move(pending_request.callback).Run(base::unexpected(error));
diff --git a/components/private_ai/testing/fake_secure_channel.cc b/components/private_ai/testing/fake_secure_channel.cc
deleted file mode 100644
index 2dad46c..0000000
--- a/components/private_ai/testing/fake_secure_channel.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2026 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/private_ai/testing/fake_secure_channel.h"
-
-#include <utility>
-#include <vector>
-
-#include "base/check.h"
-#include "base/functional/bind.h"
-#include "base/types/expected.h"
-#include "components/private_ai/proto/private_ai.pb.h"
-
-namespace private_ai {
-
-FakeSecureChannel::FakeSecureChannel(ResponseCallback callback,
-                                     DestroyCallback on_destroy)
-    : response_callback_(std::move(callback)),
-      on_destroy_(std::move(on_destroy)) {
-  CHECK(response_callback_);
-}
-
-FakeSecureChannel::~FakeSecureChannel() {
-  if (on_destroy_) {
-    std::move(on_destroy_).Run(this);
-  }
-}
-
-bool FakeSecureChannel::Write(const Request& request) {
-  proto::PrivateAiRequest request_proto;
-  if (!request_proto.ParseFromArray(request.data(), request.size())) {
-    return false;
-  }
-  written_requests_.push_back(request_proto);
-  return write_succeeds_;
-}
-
-void FakeSecureChannel::send_back_response(
-    const proto::PrivateAiResponse& response) {
-  std::vector<uint8_t> response_bytes(response.ByteSizeLong());
-  response.SerializeToArray(response_bytes.data(), response_bytes.size());
-
-  CHECK(response_callback_);
-  response_callback_.Run(std::move(response_bytes));
-}
-
-void FakeSecureChannel::send_back_error(ErrorCode error) {
-  CHECK(response_callback_);
-  response_callback_.Run(base::unexpected(error));
-}
-
-FakeSecureChannelFactory::FakeSecureChannelFactory(
-    OnCreatedCallback on_created_callback,
-    OnDestroyedCallback on_destroyed_callback)
-    : on_created_callback_(std::move(on_created_callback)),
-      on_destroyed_callback_(std::move(on_destroyed_callback)) {}
-
-FakeSecureChannelFactory::~FakeSecureChannelFactory() = default;
-
-std::unique_ptr<SecureChannel> FakeSecureChannelFactory::Create(
-    SecureChannel::ResponseCallback callback) {
-  auto secure_channel = std::make_unique<FakeSecureChannel>(
-      std::move(callback), on_destroyed_callback_);
-  on_created_callback_.Run(secure_channel.get());
-  return secure_channel;
-}
-
-}  // namespace private_ai
diff --git a/components/private_ai/testing/fake_secure_channel.h b/components/private_ai/testing/fake_secure_channel.h
deleted file mode 100644
index 62abb1d..0000000
--- a/components/private_ai/testing/fake_secure_channel.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2026 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_PRIVATE_AI_TESTING_FAKE_SECURE_CHANNEL_H_
-#define COMPONENTS_PRIVATE_AI_TESTING_FAKE_SECURE_CHANNEL_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/functional/callback.h"
-#include "components/private_ai/proto/private_ai.pb.h"
-#include "components/private_ai/secure_channel.h"
-
-namespace private_ai {
-
-class FakeSecureChannel : public SecureChannel {
- public:
-  using DestroyCallback = base::OnceCallback<void(FakeSecureChannel*)>;
-
-  explicit FakeSecureChannel(ResponseCallback callback,
-                             DestroyCallback on_destroy = {});
-  ~FakeSecureChannel() override;
-
-  // SecureChannel implementation:
-  bool Write(const Request& request) override;
-
-  // Test control methods:
-  void set_write_succeeds(bool succeeds) { write_succeeds_ = succeeds; }
-
-  const proto::PrivateAiRequest& last_written_request() const {
-    return written_requests_.back();
-  }
-
-  const std::vector<proto::PrivateAiRequest>& written_requests() const {
-    return written_requests_;
-  }
-
-  void send_back_response(const proto::PrivateAiResponse& response);
-  void send_back_error(ErrorCode error);
-
- private:
-  ResponseCallback response_callback_;
-  DestroyCallback on_destroy_;
-  std::vector<proto::PrivateAiRequest> written_requests_;
-  bool write_succeeds_ = true;
-};
-
-class FakeSecureChannelFactory : public SecureChannel::Factory {
- public:
-  using OnCreatedCallback = base::RepeatingCallback<void(FakeSecureChannel*)>;
-  using OnDestroyedCallback = base::RepeatingCallback<void(FakeSecureChannel*)>;
-
-  explicit FakeSecureChannelFactory(
-      OnCreatedCallback on_created_callback,
-      OnDestroyedCallback on_destroyed_callback = {});
-  ~FakeSecureChannelFactory() override;
-
-  // SecureChannel::Factory implementation:
-  std::unique_ptr<SecureChannel> Create(
-      SecureChannel::ResponseCallback callback) override;
-
- private:
-  OnCreatedCallback on_created_callback_;
-  OnDestroyedCallback on_destroyed_callback_;
-};
-
-}  // namespace private_ai
-
-#endif  // COMPONENTS_PRIVATE_AI_TESTING_FAKE_SECURE_CHANNEL_H_
diff --git a/components/private_ai/testing/fake_token_manager.cc b/components/private_ai/testing/fake_token_manager.cc
index 534dd236..57a48919 100644
--- a/components/private_ai/testing/fake_token_manager.cc
+++ b/components/private_ai/testing/fake_token_manager.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/check.h"
-#include "base/test/run_until.h"
 #include "base/time/time.h"
 
 namespace private_ai {
@@ -56,10 +55,6 @@
   }
 }
 
-void FakeTokenManager::WaitForPendingCallback() {
-  CHECK(base::test::RunUntil([&]() { return !pending_callbacks_.empty(); }));
-}
-
 size_t FakeTokenManager::GetPendingCallbackCount() {
   return pending_callbacks_.size();
 }
diff --git a/components/private_ai/testing/fake_token_manager.h b/components/private_ai/testing/fake_token_manager.h
index ffe1224..4322673 100644
--- a/components/private_ai/testing/fake_token_manager.h
+++ b/components/private_ai/testing/fake_token_manager.h
@@ -28,7 +28,6 @@
   void SetReturnToken(bool return_token);
   void RunPendingCallbacks();
   void RunPendingProxyCallbacks();
-  void WaitForPendingCallback();
   size_t GetPendingCallbackCount();
   size_t GetPendingProxyCallbackCount();
 
diff --git a/components/segmentation_platform/embedder/default_model/tips_notifications_ranker.cc b/components/segmentation_platform/embedder/default_model/tips_notifications_ranker.cc
index b9c866c..e3aa1b8 100644
--- a/components/segmentation_platform/embedder/default_model/tips_notifications_ranker.cc
+++ b/components/segmentation_platform/embedder/default_model/tips_notifications_ranker.cc
@@ -23,8 +23,8 @@
 // Default parameters for TipsNotificationsRanker model.
 constexpr SegmentId kSegmentId =
     SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_TIPS_NOTIFICATIONS_RANKER;
-// Update the model to include the create tab groups feature.
-constexpr int64_t kModelVersion = 7;
+// Update the model to include the customize MVT feature.
+constexpr int64_t kModelVersion = 8;
 // Store 28 buckets of input data (28 days).
 constexpr int64_t kSignalStorageLength = 28;
 // Wait until we have 0 days of data.
@@ -39,7 +39,8 @@
      {TipsNotificationsRanker::kBottomOmniboxTipIdx, kBottomOmnibox},
      {TipsNotificationsRanker::kPasswordAutofillTipIdx, kPasswordAutofill},
      {TipsNotificationsRanker::kSigninTipIdx, kSignin},
-     {TipsNotificationsRanker::kCreateTabGroupsTipIdx, kCreateTabGroups}};
+     {TipsNotificationsRanker::kCreateTabGroupsTipIdx, kCreateTabGroups},
+     {TipsNotificationsRanker::kCustomizeMVTTipIdx, kCustomizeMVT}};
 
 // Enum values for histograms.
 constexpr std::array<int32_t, 1> kEnumValueForQuickDeleteMagicStackImpression{
@@ -95,7 +96,7 @@
          features::InputContext(kGoogleLensTipShown)},
         {TipsNotificationsRanker::kBottomOmniboxTipShownIdx,
          features::InputContext(kBottomOmniboxTipShown)},
-        // V2 Tips: Password Autofill, Sign in, Create Tab Groups
+        // V2 Tips: Password Autofill, Sign in, Create Tab Groups, Customize MVT
         // Check that both the synced account and local passwords count have an
         // aggregate sum of 0 during the specified window across all instances.
         {TipsNotificationsRanker::kPasswordAutofillAccountPasswordsCountIdx,
@@ -116,12 +117,18 @@
          features::UMAEnum("TabGroups.Sync.TabGroup.Created.GroupCreateOrigin",
                            28,
                            kEnumValueForTabGroupsCreatedCount)},
+        {TipsNotificationsRanker::kNTPShownCountIdx,
+         features::UserAction("MobileNTPShown", 7)},
+        {TipsNotificationsRanker::kMVTPinnedCountIdx,
+         features::UserAction("Suggestions.ContextMenu.PinItem", 28)},
         {TipsNotificationsRanker::kPasswordAutofillTipShownIdx,
          features::InputContext(kPasswordAutofillTipShown)},
         {TipsNotificationsRanker::kSigninTipShownIdx,
          features::InputContext(kSigninTipShown)},
         {TipsNotificationsRanker::kCreateTabGroupsTipShownIdx,
-         features::InputContext(kCreateTabGroupsTipShown)}};
+         features::InputContext(kCreateTabGroupsTipShown)},
+        {TipsNotificationsRanker::kCustomizeMVTTipShownIdx,
+         features::InputContext(kCustomizeMVTTipShown)}};
 
 std::vector<int> GetTipsPriorityRankingList() {
   std::vector<int> tips_list;
@@ -131,6 +138,7 @@
     tips_list.emplace_back(TipsNotificationsRanker::kPasswordAutofillTipIdx);
     tips_list.emplace_back(TipsNotificationsRanker::kSigninTipIdx);
     tips_list.emplace_back(TipsNotificationsRanker::kCreateTabGroupsTipIdx);
+    tips_list.emplace_back(TipsNotificationsRanker::kCustomizeMVTTipIdx);
   }
 
   if (features::kTrustAndSafety.Get()) {
@@ -226,6 +234,12 @@
   return tab_groups_created_count == 0 && tip_shown == 0;
 }
 
+bool IsCustomizeMVTTipEligible(float ntp_shown_count,
+                               float mvt_pinned_count,
+                               float tip_shown) {
+  return ntp_shown_count > 5 && mvt_pinned_count == 0 && tip_shown == 0;
+}
+
 }  // namespace
 
 // static
@@ -297,7 +311,7 @@
   float lens_tip_shown = inputs[kGoogleLensTipShownIdx];
   float bottom_omnibox_tip_shown = inputs[kBottomOmniboxTipShownIdx];
 
-  // V2 Tips: Password Autofill, Sign in
+  // V2 Tips: Password Autofill, Sign in, Create Tab Groups, Customize MVT
   float password_autofill_account_passwords_count =
       inputs[kPasswordAutofillAccountPasswordsCountIdx];
   float password_autofill_local_passwords_count =
@@ -305,9 +319,12 @@
   float is_user_signed_in = inputs[kIsUserSignedInIdx];
   float signin_magic_stack_shown_count = inputs[kSigninMagicStackShownCountIdx];
   float tab_groups_created_count = inputs[kTabGroupsCreatedCountIdx];
+  float ntp_shown_count = inputs[kNTPShownCountIdx];
+  float mvt_pinned_count = inputs[kMVTPinnedCountIdx];
   float password_autofill_tip_shown = inputs[kPasswordAutofillTipShownIdx];
   float signin_tip_shown = inputs[kSigninTipShownIdx];
   float create_tab_groups_tip_shown = inputs[kCreateTabGroupsTipShownIdx];
+  float customize_mvt_tip_shown = inputs[kCustomizeMVTTipShownIdx];
 
   // Only choose an eligible tip if none have been shown for the last 7 days or
   // if the testing flags to instantly schedule a notification are active.
@@ -375,6 +392,13 @@
               has_eligible_tip = true;
             }
             break;
+          case kCustomizeMVTTipIdx:
+            if (IsCustomizeMVTTipEligible(ntp_shown_count, mvt_pinned_count,
+                                          customize_mvt_tip_shown)) {
+              response[kCustomizeMVTTipIdx] = 1;
+              has_eligible_tip = true;
+            }
+            break;
           default:
             NOTREACHED();
         }
diff --git a/components/segmentation_platform/embedder/default_model/tips_notifications_ranker.h b/components/segmentation_platform/embedder/default_model/tips_notifications_ranker.h
index 2ee4f894..3f0d66e 100644
--- a/components/segmentation_platform/embedder/default_model/tips_notifications_ranker.h
+++ b/components/segmentation_platform/embedder/default_model/tips_notifications_ranker.h
@@ -25,6 +25,7 @@
     kPasswordAutofillTipIdx,
     kSigninTipIdx,
     kCreateTabGroupsTipIdx,
+    kCustomizeMVTTipIdx,
     kLabelCount
   };
 
@@ -51,9 +52,12 @@
     kIsUserSignedInIdx,
     kSigninMagicStackShownCountIdx,
     kTabGroupsCreatedCountIdx,
+    kNTPShownCountIdx,
+    kMVTPinnedCountIdx,
     kPasswordAutofillTipShownIdx,
     kSigninTipShownIdx,
     kCreateTabGroupsTipShownIdx,
+    kCustomizeMVTTipShownIdx,
     kFeatureCount
   };
 
diff --git a/components/segmentation_platform/embedder/default_model/tips_notifications_ranker_unittest.cc b/components/segmentation_platform/embedder/default_model/tips_notifications_ranker_unittest.cc
index 00789c2..9b1ee8c 100644
--- a/components/segmentation_platform/embedder/default_model/tips_notifications_ranker_unittest.cc
+++ b/components/segmentation_platform/embedder/default_model/tips_notifications_ranker_unittest.cc
@@ -220,24 +220,37 @@
   input3[TipsFeature::kSigninMagicStackShownCountIdx] = 1;
   ExpectClassifierResults(input3, {kCreateTabGroups});
 
-  // Test QuickDelete from V1 with V2 features being used.
+  // Test Customize MVT with PasswordAutofill, Signin and Create Tab Groups
+  // being used.
   std::vector<float> input4(TipsFeature::kFeatureCount, 0);
   input4[TipsFeature::kPasswordAutofillAccountPasswordsCountIdx] = 1;
   input4[TipsFeature::kPasswordAutofillLocalPasswordsCountIdx] = 1;
   input4[TipsFeature::kIsUserSignedInIdx] = 1;
   input4[TipsFeature::kSigninMagicStackShownCountIdx] = 1;
   input4[TipsFeature::kTabGroupsCreatedCountIdx] = 1;
-  ExpectClassifierResults(input4, {kQuickDelete});
+  input4[TipsFeature::kNTPShownCountIdx] = 6;
+  ExpectClassifierResults(input4, {kCustomizeMVT});
+
+  // Test QuickDelete from V1 with V2 features being used.
+  std::vector<float> input5(TipsFeature::kFeatureCount, 0);
+  input5[TipsFeature::kPasswordAutofillAccountPasswordsCountIdx] = 1;
+  input5[TipsFeature::kPasswordAutofillLocalPasswordsCountIdx] = 1;
+  input5[TipsFeature::kIsUserSignedInIdx] = 1;
+  input5[TipsFeature::kSigninMagicStackShownCountIdx] = 1;
+  input5[TipsFeature::kTabGroupsCreatedCountIdx] = 1;
+  input5[TipsFeature::kNTPShownCountIdx] = 6;
+  input5[TipsFeature::kMVTPinnedCountIdx] = 1;
+  ExpectClassifierResults(input5, {kQuickDelete});
 
   // Test AllFeatureTipsShownCount blocks scheduling notifications.
-  std::vector<float> input5(TipsFeature::kFeatureCount, 0);
-  input5[TipsFeature::kAllFeatureTipsShownCountIdx] = 1;
-  ExpectClassifierResults(input5, {});
+  std::vector<float> input6(TipsFeature::kFeatureCount, 0);
+  input6[TipsFeature::kAllFeatureTipsShownCountIdx] = 1;
+  ExpectClassifierResults(input6, {});
 
   // Test TipShown blocks scheduling PasswordAutofill as first eligible.
-  std::vector<float> input6(TipsFeature::kFeatureCount, 0);
-  input6[TipsFeature::kPasswordAutofillTipShownIdx] = 1;
-  ExpectClassifierResults(input6, {kSignin});
+  std::vector<float> input7(TipsFeature::kFeatureCount, 0);
+  input7[TipsFeature::kPasswordAutofillTipShownIdx] = 1;
+  ExpectClassifierResults(input7, {kSignin});
 }
 
 }  // namespace segmentation_platform
diff --git a/components/segmentation_platform/public/constants.h b/components/segmentation_platform/public/constants.h
index 6191fb4..5f138bc 100644
--- a/components/segmentation_platform/public/constants.h
+++ b/components/segmentation_platform/public/constants.h
@@ -291,6 +291,7 @@
 const char kPasswordAutofill[] = "PasswordAutofill";
 const char kSignin[] = "Signin";
 const char kCreateTabGroups[] = "CreateTabGroups";
+const char kCustomizeMVT[] = "CustomizeMVT";
 
 // Input Context keys for tips notifications ranker.
 // V1 Tips: ESB, Quick Delete, Google Lens, Bottom Omnibox
@@ -302,11 +303,12 @@
 const char kQuickDeleteTipShown[] = "quick_delete_tip_shown";
 const char kGoogleLensTipShown[] = "google_lens_tip_shown";
 const char kBottomOmniboxTipShown[] = "bottom_omnibox_tip_shown";
-// V2 Tips: Password Autofill, Signin, Create Tab Groups
+// V2 Tips: Password Autofill, Signin, Create Tab Groups, Customize MVT
 const char kTipsIsUserSignedIn[] = "is_user_signed_in";
 const char kPasswordAutofillTipShown[] = "password_autofill_tip_shown";
 const char kSigninTipShown[] = "signin_tip_shown";
 const char kCreateTabGroupsTipShown[] = "create_tab_groups_tip_shown";
+const char kCustomizeMVTTipShown[] = "customize_mvt_tip_shown";
 
 }  // namespace segmentation_platform
 
diff --git a/components/segmentation_platform/tools/user_actions.txt b/components/segmentation_platform/tools/user_actions.txt
index 48c8ec29..8554068 100644
--- a/components/segmentation_platform/tools/user_actions.txt
+++ b/components/segmentation_platform/tools/user_actions.txt
@@ -24,6 +24,7 @@
 MobileMenuShare
 MobileMenuTranslate
 MobileNTPMostVisited
+MobileNTPShown
 MobileNewTabOpened
 MobileNewTabShown
 MobileOmniboxLens
@@ -45,6 +46,7 @@
 SafeBrowsing.Settings.EnhancedProtectionClicked
 SharingHubAndroid.SendTabToSelfSelected
 Suggestions.Content.Opened
+Suggestions.ContextMenu.PinItem
 TabGroup.Created.OpenInNewTab
 TasksSurface.FakeBox.Lens
 UserActionName
diff --git a/components/sessions/core/command_storage_backend.cc b/components/sessions/core/command_storage_backend.cc
index 360b23c..a5c3dd3 100644
--- a/components/sessions/core/command_storage_backend.cc
+++ b/components/sessions/core/command_storage_backend.cc
@@ -34,10 +34,10 @@
 
 namespace sessions {
 
-using SessionType = CommandStorageManager::SessionType;
-
 namespace {
 
+using SessionType = CommandStorageManager::SessionType;
+
 // File version numbers:
 // kFileVersion1 = 1; No longer supported. Used in production prior to commit
 //   223e5cd on 2021-05-25.
@@ -365,31 +365,31 @@
 }
 
 // Returns the directory the files are stored in.
-base::FilePath GetSessionDirName(CommandStorageManager::SessionType type,
+base::FilePath GetSessionDirName(SessionType type,
                                  const base::FilePath& supplied_path) {
-  if (type == CommandStorageManager::kOther) {
+  if (type == SessionType::kOther) {
     return supplied_path.DirName();
   }
   return supplied_path.Append(kSessionsDirectory);
 }
 
 base::FilePath::StringType GetSessionBaseName(
-    CommandStorageManager::SessionType type,
+    SessionType type,
     const base::FilePath& supplied_path) {
   switch (type) {
-    case CommandStorageManager::kAppRestore:
+    case SessionType::kAppRestore:
       return kAppSessionFileNamePrefix;
-    case CommandStorageManager::kTabRestore:
+    case SessionType::kTabRestore:
       return kTabSessionFileNamePrefix;
-    case CommandStorageManager::kSessionRestore:
+    case SessionType::kSessionRestore:
       return kSessionFileNamePrefix;
-    case CommandStorageManager::kOther:
+    case SessionType::kOther:
       return supplied_path.BaseName().value();
   }
 }
 
 base::FilePath::StringType GetSessionFilename(
-    CommandStorageManager::SessionType type,
+    SessionType type,
     const base::FilePath& supplied_path,
     const base::FilePath::StringType& timestamp_str) {
   return base::JoinString(
@@ -397,23 +397,6 @@
       kTimestampSeparator);
 }
 
-base::FilePath GetLegacySessionPath(CommandStorageManager::SessionType type,
-                                    const base::FilePath& base_path,
-                                    bool current) {
-  switch (type) {
-    case CommandStorageManager::kAppRestore:
-      return base_path;
-    case CommandStorageManager::kTabRestore:
-      return base_path.Append(current ? kLegacyCurrentTabSessionFileName
-                                      : kLegacyLastTabSessionFileName);
-    case CommandStorageManager::kSessionRestore:
-      return base_path.Append(current ? kLegacyCurrentSessionFileName
-                                      : kLegacyLastSessionFileName);
-    case CommandStorageManager::kOther:
-      return base_path;
-  }
-}
-
 }  // namespace
 
 CommandStorageBackend::ReadCommandsResult::ReadCommandsResult() = default;
@@ -536,7 +519,7 @@
 // static
 std::set<base::FilePath> CommandStorageBackend::GetSessionFilePaths(
     const base::FilePath& path,
-    CommandStorageManager::SessionType type) {
+    SessionType type) {
   std::set<base::FilePath> result;
   for (const auto& info : GetSessionFilesSortedByReverseTimestamp(path, type)) {
     result.insert(info.path);
@@ -570,7 +553,7 @@
 
 void CommandStorageBackend::MoveCurrentSessionToLastSession() {
   // TODO(sky): make this work for kOther.
-  DCHECK_NE(CommandStorageManager::SessionType::kOther, type_);
+  DCHECK_NE(SessionType::kOther, type_);
 
   InitIfNecessary();
   CloseFile();
@@ -743,15 +726,6 @@
       return session;
     }
   }
-
-  // If no last session was found, use the legacy session if present.
-  // The legacy session is considered to have a timestamp of 0, before any
-  // new session.
-  base::FilePath legacy_session =
-      GetLegacySessionPath(type_, supplied_path_, true);
-  if (base::PathExists(legacy_session)) {
-    return SessionInfo{legacy_session, base::Time()};
-  }
   return std::nullopt;
 }
 
@@ -764,31 +738,13 @@
       base::DeleteFile(session.path);
     }
   }
-
-  // Delete legacy session files, unless they are being used.
-  const base::FilePath legacy_current_session_path =
-      GetLegacySessionPath(type_, supplied_path_, true);
-  if (last_session_info_ &&
-      legacy_current_session_path != last_session_info_->path &&
-      base::PathExists(legacy_current_session_path)) {
-    base::DeleteFile(legacy_current_session_path);
-  }
-
-  // `kOther` does not differentiate between last and current.
-  if (type_ != CommandStorageManager::kOther) {
-    const base::FilePath legacy_last_session_path =
-        GetLegacySessionPath(type_, supplied_path_, false);
-    if (base::PathExists(legacy_last_session_path)) {
-      base::DeleteFile(legacy_last_session_path);
-    }
-  }
 }
 
 // static
 std::vector<CommandStorageBackend::SessionInfo>
 CommandStorageBackend::GetSessionFilesSortedByReverseTimestamp(
     const base::FilePath& path,
-    CommandStorageManager::SessionType type) {
+    SessionType type) {
   std::vector<SessionInfo> sessions;
   base::FileEnumerator file_enum(
       GetSessionDirName(type, path), false, base::FileEnumerator::FILES,
diff --git a/components/sessions/core/command_storage_backend.h b/components/sessions/core/command_storage_backend.h
index e5702cf..0534a9e8 100644
--- a/components/sessions/core/command_storage_backend.h
+++ b/components/sessions/core/command_storage_backend.h
@@ -246,7 +246,7 @@
   // Timestamp when this session was started.
   base::Time timestamp_;
 
-  // Data for the last session. If unset, fallback to legacy session data.
+  // Data for the last session.
   std::optional<SessionInfo> last_session_info_;
 
   // Paths of the two most recently written files with a valid marker (the
diff --git a/components/sessions/core/command_storage_backend_unittest.cc b/components/sessions/core/command_storage_backend_unittest.cc
index ab0bea2..22a8a94 100644
--- a/components/sessions/core/command_storage_backend_unittest.cc
+++ b/components/sessions/core/command_storage_backend_unittest.cc
@@ -40,6 +40,7 @@
 namespace {
 
 using SessionCommands = std::vector<std::unique_ptr<SessionCommand>>;
+using SessionType = CommandStorageManager::SessionType;
 
 struct TestData {
   SessionCommand::id_type command_id;
@@ -136,7 +137,11 @@
                          .AppendASCII("data")
                          .AppendASCII("sessions");
     test_file_path = test_file_path.AppendASCII(test_data_filename);
-    return base::CopyFile(test_file_path, file_path());
+    return base::CopyFile(test_file_path,
+                          file_path()
+                              .InsertBeforeExtension(kTimestampSeparator)
+                              // 1234 is a dummy timestamp.
+                              .InsertBeforeExtensionUTF8("1234"));
   }
 
   const base::FilePath& file_path() const { return file_path_; }
@@ -151,45 +156,6 @@
   base::ScopedTempDir temp_dir_;
 };
 
-TEST_F(CommandStorageBackendTest, MigrateOther) {
-  scoped_refptr<CommandStorageBackend> backend = CreateBackend();
-  struct TestData data = {1, "a"};
-  SessionCommands commands;
-  commands.push_back(CreateCommandFromData(data));
-  backend->AppendCommands(std::move(commands), true, base::DoNothing());
-  const auto path = backend->current_path_for_testing();
-  EXPECT_EQ(file_path().DirName(), path.DirName());
-  auto base_name = file_path().BaseName().value();
-  EXPECT_EQ(base_name, path.BaseName().value().substr(0, base_name.length()));
-  backend = nullptr;
-
-  // Move the file to the original path. This gives the logic before kOther
-  // started using timestamps.
-  ASSERT_TRUE(base::PathExists(path));
-  ASSERT_TRUE(base::Move(path, file_path()));
-
-  // Create the backend, should get back the data written.
-  backend = CreateBackend();
-  commands = backend->ReadLastSessionCommands().commands;
-  ASSERT_EQ(1U, commands.size());
-  AssertCommandEqualsData(data, commands[0].get());
-
-  // Write some more data.
-  struct TestData data2 = {1, "b"};
-  commands.clear();
-  commands.push_back(CreateCommandFromData(data2));
-  backend->AppendCommands(std::move(commands), true, base::DoNothing());
-
-  // Recreate, verify updated data read back and the original file has been
-  // removed.
-  backend = nullptr;
-  backend = CreateBackend();
-  commands = backend->ReadLastSessionCommands().commands;
-  EXPECT_FALSE(base::PathExists(file_path()));
-  ASSERT_EQ(1U, commands.size());
-  AssertCommandEqualsData(data2, commands[0].get());
-}
-
 TEST_F(CommandStorageBackendTest, SimpleReadWrite) {
   scoped_refptr<CommandStorageBackend> backend = CreateBackend();
   struct TestData data = {1, "a"};
@@ -627,8 +593,8 @@
 }
 
 TEST_F(CommandStorageBackendTest, GetSessionFiles) {
-  EXPECT_TRUE(CommandStorageBackend::GetSessionFilePaths(
-                  file_path(), CommandStorageManager::kOther)
+  EXPECT_TRUE(CommandStorageBackend::GetSessionFilePaths(file_path(),
+                                                         SessionType::kOther)
                   .empty());
   ASSERT_TRUE(base::WriteFile(file_path(), ""));
   // Not a valid name, as doesn't contain timestamp separator.
@@ -640,8 +606,8 @@
   // Valid name, but should not be returned as beginning doesn't match.
   ASSERT_TRUE(
       base::WriteFile(file_path().DirName().AppendASCII("Foo_125"), ""));
-  auto paths = CommandStorageBackend::GetSessionFilePaths(
-      file_path(), CommandStorageManager::kOther);
+  auto paths = CommandStorageBackend::GetSessionFilePaths(file_path(),
+                                                          SessionType::kOther);
   ASSERT_EQ(1u, paths.size());
   EXPECT_EQ("Session_124", paths.begin()->BaseName().MaybeAsASCII());
 }
diff --git a/components/sessions/core/command_storage_manager.h b/components/sessions/core/command_storage_manager.h
index 4fba3d8..ec92746 100644
--- a/components/sessions/core/command_storage_manager.h
+++ b/components/sessions/core/command_storage_manager.h
@@ -48,7 +48,7 @@
   // TODO(sky): this enum is purely for legacy reasons, and should be replaced
   // with consumers building the path. Remove in approximately a year (1/2022),
   // when we shouldn't need to worry too much about migrating older data.
-  enum SessionType { kAppRestore, kSessionRestore, kTabRestore, kOther };
+  enum class SessionType { kAppRestore, kSessionRestore, kTabRestore, kOther };
 
   // Creates a new CommandStorageManager. `delegate` is not owned by this and
   // must outlive this.
diff --git a/components/sessions/core/command_storage_manager_unittest.cc b/components/sessions/core/command_storage_manager_unittest.cc
index 899a5c23..44d5184 100644
--- a/components/sessions/core/command_storage_manager_unittest.cc
+++ b/components/sessions/core/command_storage_manager_unittest.cc
@@ -15,6 +15,8 @@
 
 namespace sessions {
 
+using SessionType = CommandStorageManager::SessionType;
+
 class CommandStorageManagerTest : public testing::Test {
  protected:
   // testing::TestWithParam:
@@ -47,8 +49,7 @@
 
 TEST_F(CommandStorageManagerTest, OnErrorWritingSessionCommands) {
   TestCommandStorageManagerDelegate delegate;
-  CommandStorageManager manager(CommandStorageManager::kOther, path_,
-                                &delegate);
+  CommandStorageManager manager(SessionType::kOther, path_, &delegate);
   CommandStorageManagerTestHelper test_helper(&manager);
   manager.set_pending_reset(true);
   // Write a command, the delegate should not be notified of an error.
diff --git a/components/sessions/core/session_constants.cc b/components/sessions/core/session_constants.cc
index de8d6babb..d1d50f4 100644
--- a/components/sessions/core/session_constants.cc
+++ b/components/sessions/core/session_constants.cc
@@ -20,16 +20,6 @@
 
 const base::FilePath::CharType kTimestampSeparator[] = FILE_PATH_LITERAL("_");
 
-const base::FilePath::StringViewType kLegacyCurrentTabSessionFileName =
-    FILE_PATH_LITERAL("Current Tabs");
-const base::FilePath::StringViewType kLegacyLastTabSessionFileName =
-    FILE_PATH_LITERAL("Last Tabs");
-
-const base::FilePath::StringViewType kLegacyCurrentSessionFileName =
-    FILE_PATH_LITERAL("Current Session");
-const base::FilePath::StringViewType kLegacyLastSessionFileName =
-    FILE_PATH_LITERAL("Last Session");
-
 const int gMaxPersistNavigationCount = 6;
 
 }  // namespace sessions
diff --git a/components/sessions/core/session_constants.h b/components/sessions/core/session_constants.h
index f30ccfe..7224672 100644
--- a/components/sessions/core/session_constants.h
+++ b/components/sessions/core/session_constants.h
@@ -32,22 +32,6 @@
 // timestamp.
 extern const base::FilePath::CharType SESSIONS_EXPORT kTimestampSeparator[];
 
-// TODO(sky): remove the legacy files around ~1/2022.
-
-// Legacy file names (current and previous) for a type of TAB.
-// Used before Chrome 85.
-extern const base::FilePath::StringViewType SESSIONS_EXPORT
-    kLegacyCurrentTabSessionFileName;
-extern const base::FilePath::StringViewType SESSIONS_EXPORT
-    kLegacyLastTabSessionFileName;
-
-// Legacy file names (current and previous) for a type of SESSION.
-// Used before Chrome 85.
-extern const base::FilePath::StringViewType SESSIONS_EXPORT
-    kLegacyCurrentSessionFileName;
-extern const base::FilePath::StringViewType SESSIONS_EXPORT
-    kLegacyLastSessionFileName;
-
 // The maximum number of navigation entries in each direction to persist.
 extern const int SESSIONS_EXPORT gMaxPersistNavigationCount;
 
diff --git a/components/sessions/core/tab_restore_service_impl.cc b/components/sessions/core/tab_restore_service_impl.cc
index f90deb3..5728c8e4 100644
--- a/components/sessions/core/tab_restore_service_impl.cc
+++ b/components/sessions/core/tab_restore_service_impl.cc
@@ -639,7 +639,7 @@
     TabRestoreServiceClient* client)
     : client_(client),
       command_storage_manager_(std::make_unique<CommandStorageManager>(
-          CommandStorageManager::kTabRestore,
+          CommandStorageManager::SessionType::kTabRestore,
           client_->GetPathToSaveTo(),
           this)),
       tab_restore_service_helper_(nullptr),
diff --git a/components/translate/content/android/java/src/org/chromium/components/translate/TranslateMessageTest.java b/components/translate/content/android/java/src/org/chromium/components/translate/TranslateMessageTest.java
index 158bd6dbd..a9a29b7 100644
--- a/components/translate/content/android/java/src/org/chromium/components/translate/TranslateMessageTest.java
+++ b/components/translate/content/android/java/src/org/chromium/components/translate/TranslateMessageTest.java
@@ -17,14 +17,16 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.mockito.stubbing.Answer;
 
 import org.chromium.base.UnownedUserDataHost;
@@ -62,9 +64,10 @@
 
     @Captor ArgumentCaptor<PropertyModel> mPropertyModelCaptor;
 
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
 
         TranslateMessageJni.setInstanceForTesting(mMockJni);
     }
diff --git a/components/ui_devtools/devtools_server.cc b/components/ui_devtools/devtools_server.cc
index 6014707..aa7e781 100644
--- a/components/ui_devtools/devtools_server.cc
+++ b/components/ui_devtools/devtools_server.cc
@@ -260,6 +260,12 @@
   on_socket_connected_ = std::move(on_socket_connected);
 }
 
+void UiDevToolsServer::SetOnClientConnectedForTesting(
+    base::OnceClosure on_client_connected) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_);
+  on_client_connected_ = std::move(on_client_connected);
+}
+
 void UiDevToolsServer::OnWebSocketRequestForTesting(
     int connection_id,
     net::HttpServerRequestInfo info) {
@@ -345,6 +351,9 @@
       FROM_HERE, base::BindOnce(&IOThreadData::AcceptWebSocket,
                                 base::Unretained(io_thread_data_.get()),
                                 connection_id, std::move(info)));
+  if (on_client_connected_) {
+    std::move(on_client_connected_).Run();
+  }
 }
 
 void UiDevToolsServer::OnWebSocketMessage(int connection_id, std::string data) {
diff --git a/components/ui_devtools/devtools_server.h b/components/ui_devtools/devtools_server.h
index 2506a9c..c068ac93 100644
--- a/components/ui_devtools/devtools_server.h
+++ b/components/ui_devtools/devtools_server.h
@@ -93,6 +93,8 @@
   // Sets a callback that tests can use to wait for the server to be ready to
   // accept connections.
   void SetOnSocketConnectedForTesting(base::OnceClosure on_socket_connected);
+  // Sets a callback that tests can use to wait for a client to connect.
+  void SetOnClientConnectedForTesting(base::OnceClosure on_client_connected);
   // Allows calling OnWebSocketRequest() with unexpected connection IDs for
   // tests, bypassing the HttpServer.
   void OnWebSocketRequestForTesting(int connection_id,
@@ -155,6 +157,9 @@
   // Invoked once the server has been started.
   base::OnceClosure on_socket_connected_ GUARDED_BY_CONTEXT(main_sequence_);
 
+  // Invoked when a client connects.
+  base::OnceClosure on_client_connected_ GUARDED_BY_CONTEXT(main_sequence_);
+
   // The server (owned by Chrome for now)
   static UiDevToolsServer* devtools_server_;
 
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc
index 5a1c0cd..99c00a5 100644
--- a/components/viz/common/features.cc
+++ b/components/viz/common/features.cc
@@ -189,6 +189,11 @@
 BASE_FEATURE(kAckCopyOutputRequestEarlyForViewTransition,
              base::FEATURE_ENABLED_BY_DEFAULT);
 
+// If enabled, other frame sinks are throttled when a frame sink is handling
+// user interaction.
+BASE_FEATURE(kThrottleFrameSinksOnInteraction,
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 BASE_FEATURE(kAllowUndamagedNonrootRenderPassToSkip,
 #if BUILDFLAG(IS_MAC)
              base::FEATURE_ENABLED_BY_DEFAULT);
@@ -461,6 +466,11 @@
   return base::FeatureList::IsEnabled(features::kOnBeginFrameThrottleVideo);
 }
 
+bool ShouldThrottleWhenInteractiveFrameSinks() {
+  return base::FeatureList::IsEnabled(
+      features::kThrottleFrameSinksOnInteraction);
+}
+
 bool ShouldAckOnSurfaceActivationWhenInteractive() {
   return base::FeatureList::IsEnabled(
       features::kAckOnSurfaceActivationWhenInteractive);
diff --git a/components/viz/common/features.h b/components/viz/common/features.h
index f0cb9a5..c10f971 100644
--- a/components/viz/common/features.h
+++ b/components/viz/common/features.h
@@ -87,6 +87,8 @@
 
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(
     kAckCopyOutputRequestEarlyForViewTransition);
+VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kThrottleFrameSinksOnInteraction);
+VIZ_COMMON_EXPORT bool ShouldThrottleWhenInteractiveFrameSinks();
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kAllowUndamagedNonrootRenderPassToSkip);
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(
     kAllowForceMergeRenderPassWithRequireOverlayQuads);
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index 10497f2..7aab8007 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -629,6 +629,7 @@
     "frame_sinks/begin_frame_tracker_unittest.cc",
     "frame_sinks/compositor_frame_sink_support_unittest.cc",
     "frame_sinks/frame_sink_bundle_impl_unittest.cc",
+    "frame_sinks/frame_sink_manager_priority_unittest.cc",
     "frame_sinks/frame_sink_manager_unittest.cc",
     "frame_sinks/frame_sink_throttler_unittest.cc",
     "frame_sinks/surface_references_unittest.cc",
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
index d5ecf0e..21ae287 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -281,6 +281,10 @@
   throttler_.SetAllowThrottling(allowed);
 }
 
+void CompositorFrameSinkSupport::SetThrottledDueToInteraction(bool throttled) {
+  throttler_.SetThrottledDueToInteraction(throttled);
+}
+
 void CompositorFrameSinkSupport::SetIsHandlingInteraction(
     bool is_handling_interaction) {
   if (is_handling_interaction_ != is_handling_interaction) {
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
index 1009146..53a5129 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -158,6 +158,9 @@
   // regardless of any other throttling.
   void SetAllowThrottling(bool allowed);
 
+  // If other clients are interactive, reduce frame cadence if `throttled`.
+  void SetThrottledDueToInteraction(bool throttled);
+
   // SurfaceClient implementation.
   void OnSurfaceCommitted(Surface* surface) override;
   void OnSurfaceActivated(Surface* surface) override;
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
index 7dc50c6..59ce418f 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -1996,6 +1996,14 @@
   support->SetNeedsBeginFrame(false);
 }
 
+TEST_P(CompositorFrameSinkSupportTest, InteractionsThrottleToHalfFrameRate) {
+  constexpr base::TimeDelta kNativeInterval = BeginFrameArgs::DefaultInterval();
+  constexpr base::TimeDelta kThrottledInterval = kNativeInterval * 2;
+  support_->SetThrottledDueToInteraction(true);
+  EXPECT_EQ(support_->GetThrottlerForTesting().begin_frame_interval(),
+            kThrottledInterval);
+}
+
 TEST_P(CompositorFrameSinkSupportTest, HandlesSmallErrorInBeginFrameTimes) {
   FakeExternalBeginFrameSource begin_frame_source(0.f, false);
 
@@ -2008,7 +2016,7 @@
   support->SetNeedsBeginFrame(true);
   constexpr base::TimeDelta kNativeInterval = BeginFrameArgs::DefaultInterval();
   constexpr base::TimeDelta kThrottledInterval = kNativeInterval * 2;
-  support->SetThrottleInterval(kThrottledInterval);
+  manager_->Throttle({support->frame_sink_id()}, kThrottledInterval);
   constexpr base::TimeDelta kEpsilon = base::Microseconds(2);
 
   base::TimeTicks frame_time;
@@ -2070,7 +2078,7 @@
   EXPECT_EQ(support_->GetThrottlerForTesting().begin_frame_interval(),
             base::TimeDelta());
 
-  support_->SetThrottleInterval(base::Milliseconds(32));
+  manager_->Throttle({support_->frame_sink_id()}, base::Milliseconds(32));
   EXPECT_EQ(support_->GetThrottlerForTesting().begin_frame_interval(),
             base::Milliseconds(32));
 }
@@ -2130,7 +2138,7 @@
   static constexpr base::TimeDelta kThrottledFrameInterval = base::Hertz(5);
   // Request BeginFrames.
   support_->SetNeedsBeginFrame(true);
-  support_->SetThrottleInterval(kThrottledFrameInterval);
+  manager_->Throttle({support_->frame_sink_id()}, kThrottledFrameInterval);
   ASSERT_THAT(BeginFrameArgs::DefaultInterval(), Ne(kThrottledFrameInterval));
 
   base::TimeTicks frame_time = base::TimeTicks::Now();
@@ -2488,7 +2496,7 @@
   static constexpr base::TimeDelta kThrottledFrameInterval = base::Hertz(5);
   // Request BeginFrames.
   support_->SetNeedsBeginFrame(true);
-  support_->SetThrottleInterval(kThrottledFrameInterval);
+  manager_->Throttle({support_->frame_sink_id()}, kThrottledFrameInterval);
   ASSERT_THAT(BeginFrameArgs::DefaultInterval(), Ne(kThrottledFrameInterval));
 
   base::TimeTicks frame_time = base::TimeTicks::Now();
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
index 80f5d91..6727229 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
+++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -723,9 +723,19 @@
   }
 
   captured_frame_sink_ids_.erase(frame_sink_id);
-  interactive_frame_sink_ids_.erase(frame_sink_id);
+  const bool was_interactive = interactive_frame_sink_ids_.erase(frame_sink_id);
 
   support_map_.erase(frame_sink_id);
+
+  // If we delete the last interactive frame sink we must do a global update
+  // since it was causing all other frame sinks to throttle.
+  if (was_interactive && interactive_frame_sink_ids_.empty()) {
+    UpdateThrottling();
+  } else {
+    // The standard path only updates the sub tree to avoid N^2 time complexity
+    // when unregistering all frame sinks
+    UpdateThrottlingRecursively(frame_sink_id);
+  }
 }
 
 void FrameSinkManagerImpl::RegisterBeginFrameSource(
@@ -1136,9 +1146,9 @@
     interactive_frame_sink_ids_.erase(frame_sink_id);
   }
 
-  // TODO(crbug.com/467315115): Interaction throttling changes global
-  // state, so do a full throttling update.
-  // UpdateThrottling();
+  // Interaction throttling changes global state, so do a full throttling
+  // update.
+  UpdateThrottling();
 }
 
 void FrameSinkManagerImpl::UpdateThrottlingRecursively(
@@ -1152,18 +1162,26 @@
                     if (auto* support = GetFrameSinkForId(child_id)) {
                       support->SetThrottleInterval(default_throttle);
                       support->SetAllowThrottling(true);
+                      if (features::ShouldThrottleWhenInteractiveFrameSinks()) {
+                        support->SetThrottledDueToInteraction(
+                            !interactive_frame_sink_ids_.empty());
+                      }
                     }
                   });
 
   bool check_throttles = ThrottleIntervalHasEffect();
   bool check_captures = !captured_frame_sink_ids_.empty();
+  bool check_interactions = base::FeatureList::IsEnabled(
+                                features::kThrottleFrameSinksOnInteraction) &&
+                            !interactive_frame_sink_ids_.empty();
 
-  if (!check_throttles && !check_captures) {
+  if (!check_throttles && !check_captures && !check_interactions) {
     return;
   }
 
   base::flat_set<FrameSinkId> throttles;
   base::flat_set<FrameSinkId> captures;
+  base::flat_set<FrameSinkId> interactions;
 
   // Identify anything which would affect throttling from ancestors or
   // descendants.
@@ -1181,6 +1199,11 @@
     if (check_captures && captured_frame_sink_ids_.contains(id)) {
       captures.insert(root);
     }
+
+    // Throttle all clients which are not interactive.
+    if (check_interactions && interactive_frame_sink_ids_.contains(id)) {
+      interactions.insert(id);
+    }
   };
 
   RecurseParents(frame_sink_id, [&](const FrameSinkId& parent) {
@@ -1194,7 +1217,7 @@
   });
 
   // Apply the identified rules.
-  ApplyThrottlingRules(throttles, captures);
+  ApplyThrottlingRules(throttles, captures, interactions);
 }
 
 void FrameSinkManagerImpl::Throttle(const std::vector<FrameSinkId>& ids,
@@ -1217,7 +1240,8 @@
 
 void FrameSinkManagerImpl::ApplyThrottlingRules(
     const base::flat_set<FrameSinkId>& throttled_roots,
-    const base::flat_set<FrameSinkId>& captured_roots) {
+    const base::flat_set<FrameSinkId>& captured_roots,
+    const base::flat_set<FrameSinkId>& interacting_roots) {
   // Apply throttling
   if (ThrottleIntervalHasEffect()) {
     for (const auto& id : throttled_roots) {
@@ -1237,18 +1261,32 @@
       }
     });
   }
+
+  // Interacting clients should not be throttled.
+  for (const FrameSinkId& id : interacting_roots) {
+    if (auto* support = GetFrameSinkForId(id)) {
+      support->SetThrottledDueToInteraction(false);
+    }
+  }
 }
 
 void FrameSinkManagerImpl::UpdateThrottling() {
-  // Clear previous throttling on all frame sinks.
-  const base::TimeDelta default_throttle =
+  // Update throttling on all frame sinks to an initial state, which is
+  // either the global state or the unthrottled state.
+  const base::TimeDelta gloabl_throttle =
       global_throttle_interval_.value_or(base::TimeDelta());
+
   for (auto& [id, support] : support_map_) {
-    support->SetThrottleInterval(default_throttle);
+    support->SetThrottleInterval(gloabl_throttle);
     support->SetAllowThrottling(true);
+    if (features::ShouldThrottleWhenInteractiveFrameSinks()) {
+      support->SetThrottledDueToInteraction(
+          !interactive_frame_sink_ids_.empty());
+    }
   }
 
-  ApplyThrottlingRules(frame_sink_ids_to_throttle_, captured_frame_sink_ids_);
+  ApplyThrottlingRules(frame_sink_ids_to_throttle_, captured_frame_sink_ids_,
+                       interactive_frame_sink_ids_);
 }
 
 bool FrameSinkManagerImpl::ThrottleIntervalHasEffect() const {
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.h b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
index a851f18..5ab48ff 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_impl.h
+++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
@@ -541,8 +541,10 @@
   // Applies throttling to all descendants of `throttled_roots`, and disables
   // throttling for all descendants of `captured_roots` (e.g. during video
   // capture).
-  void ApplyThrottlingRules(const base::flat_set<FrameSinkId>& throttled_roots,
-                            const base::flat_set<FrameSinkId>& captured_roots);
+  void ApplyThrottlingRules(
+      const base::flat_set<FrameSinkId>& throttled_roots,
+      const base::flat_set<FrameSinkId>& captured_roots,
+      const base::flat_set<FrameSinkId>& interacting_roots);
 
   // Check to see if |throttle_interval_| has any effect. For example if
   // |global_throttle_interval_| is longer then |throttle_interval| it will
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_priority_unittest.cc b/components/viz/service/frame_sinks/frame_sink_manager_priority_unittest.cc
new file mode 100644
index 0000000..1196f39
--- /dev/null
+++ b/components/viz/service/frame_sinks/frame_sink_manager_priority_unittest.cc
@@ -0,0 +1,261 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <vector>
+
+#include "base/test/scoped_feature_list.h"
+#include "components/viz/common/features.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
+#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/service/surfaces/surface_manager.h"
+#include "components/viz/test/compositor_frame_helpers.h"
+#include "components/viz/test/fake_external_begin_frame_source.h"
+#include "components/viz/test/mock_compositor_frame_sink_client.h"
+#include "components/viz/test/test_output_surface_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace viz {
+namespace {
+
+constexpr FrameSinkId kFrameSinkIdA(1, 1);
+constexpr FrameSinkId kFrameSinkIdB(2, 1);
+constexpr FrameSinkId kFrameSinkIdC(3, 1);
+
+class FrameSinkManagerPriorityTest : public testing::Test {
+ public:
+  FrameSinkManagerPriorityTest() {
+    feature_list_.InitAndEnableFeature(
+        features::kThrottleFrameSinksOnInteraction);
+    FrameSinkManagerImpl::InitParams init_params(&output_surface_provider_);
+    manager_ = std::make_unique<FrameSinkManagerImpl>(std::move(init_params));
+  }
+  ~FrameSinkManagerPriorityTest() override = default;
+
+  std::unique_ptr<CompositorFrameSinkSupport> CreateCompositorFrameSinkSupport(
+      const FrameSinkId& frame_sink_id) {
+    auto support = std::make_unique<CompositorFrameSinkSupport>(
+        &mock_client_, manager_.get(), frame_sink_id, /*is_root=*/false);
+    support->SetBeginFrameSource(&begin_frame_source_);
+    // Use a fixed vsync to avoid rounding issues in tests.
+    support->GetThrottlerForTesting().SetLastKnownVsync(base::Hertz(60),
+                                                        base::Hertz(60));
+    return support;
+  }
+
+  void SubmitFrame(CompositorFrameSinkSupport* support,
+                   bool is_handling_interaction) {
+    CompositorFrame frame = MakeDefaultCompositorFrame();
+    frame.metadata.is_handling_interaction = is_handling_interaction;
+    LocalSurfaceId local_surface_id(1, 1, base::UnguessableToken::Create());
+    support->SubmitCompositorFrame(local_surface_id, std::move(frame));
+  }
+
+  base::TimeDelta GetThrottleInterval(CompositorFrameSinkSupport* support) {
+    return support->GetThrottlerForTesting().begin_frame_interval();
+  }
+
+ protected:
+  base::test::ScopedFeatureList feature_list_;
+  TestOutputSurfaceProvider output_surface_provider_;
+  std::unique_ptr<FrameSinkManagerImpl> manager_;
+  MockCompositorFrameSinkClient mock_client_;
+  FakeExternalBeginFrameSource begin_frame_source_{0.f, false};
+};
+
+TEST_F(FrameSinkManagerPriorityTest, ThrottleUnimportantFrameSinks) {
+  auto support_a = CreateCompositorFrameSinkSupport(kFrameSinkIdA);
+  auto support_b = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
+
+  // Initially no throttling.
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_a.get()));
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_b.get()));
+
+  // Submit interactive frame to A.
+  SubmitFrame(support_a.get(), /*is_handling_interaction=*/true);
+
+  // B should be throttled. A should not.
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_a.get()));
+  EXPECT_EQ(base::Hertz(60) * 2, GetThrottleInterval(support_b.get()));
+
+  // Submit non-interactive frame to A.
+  SubmitFrame(support_a.get(), /*is_handling_interaction=*/false);
+
+  // Throttling should be removed.
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_a.get()));
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_b.get()));
+}
+
+TEST_F(FrameSinkManagerPriorityTest, MultipleInteractions) {
+  auto support_a = CreateCompositorFrameSinkSupport(kFrameSinkIdA);
+  auto support_b = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
+  auto support_c = CreateCompositorFrameSinkSupport(kFrameSinkIdC);
+
+  // A interacts. B and C throttled.
+  SubmitFrame(support_a.get(), true);
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_a.get()));
+  EXPECT_EQ(base::Hertz(60) * 2, GetThrottleInterval(support_b.get()));
+  EXPECT_EQ(base::Hertz(60) * 2, GetThrottleInterval(support_c.get()));
+
+  // B interacts too. C still throttled. A and B not.
+  SubmitFrame(support_b.get(), true);
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_a.get()));
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_b.get()));
+  EXPECT_EQ(base::Hertz(60) * 2, GetThrottleInterval(support_c.get()));
+
+  // A stops. B still interacting. C still throttled. A becomes throttled.
+  SubmitFrame(support_a.get(), false);
+  EXPECT_EQ(base::Hertz(60) * 2, GetThrottleInterval(support_a.get()));
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_b.get()));
+  EXPECT_EQ(base::Hertz(60) * 2, GetThrottleInterval(support_c.get()));
+
+  // B stops. All clear.
+  SubmitFrame(support_b.get(), false);
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_a.get()));
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_b.get()));
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_c.get()));
+}
+
+TEST_F(FrameSinkManagerPriorityTest, ExplicitThrottlingWinsIfSlower) {
+  auto support_a = CreateCompositorFrameSinkSupport(kFrameSinkIdA);
+  auto support_b = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
+
+  // Throttle B explicitly to 10Hz (100ms).
+  manager_->Throttle({kFrameSinkIdB}, base::Seconds(0.1));
+  EXPECT_EQ(base::Seconds(0.1), GetThrottleInterval(support_b.get()));
+
+  // A interacts. Interaction implies 30Hz (33ms).
+  // B is already at 100ms. 100ms > 33ms, so it should stay at 100ms.
+  SubmitFrame(support_a.get(), true);
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_a.get()));
+  EXPECT_EQ(base::Seconds(0.1), GetThrottleInterval(support_b.get()));
+
+  // Throttle B explicitly to 60Hz (16ms).
+  // Interaction implies 30Hz (33ms).
+  // 33ms > 16ms, so it should be throttled to 33ms.
+  manager_->Throttle({kFrameSinkIdB}, base::Seconds(0.016));
+  EXPECT_EQ(base::Hertz(60) * 2, GetThrottleInterval(support_b.get()));
+}
+
+TEST_F(FrameSinkManagerPriorityTest, ExplicitThrottlingOnInteractiveSink) {
+  auto support_a = CreateCompositorFrameSinkSupport(kFrameSinkIdA);
+
+  // A interacts.
+  SubmitFrame(support_a.get(), true);
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_a.get()));
+
+  // Throttle A explicitly to 1Hz.
+  // Explicit throttling should override interaction status.
+  manager_->Throttle({kFrameSinkIdA}, base::Seconds(1));
+  EXPECT_EQ(base::Seconds(1), GetThrottleInterval(support_a.get()));
+}
+
+TEST_F(FrameSinkManagerPriorityTest, CapturedFrameSinksAreNotThrottled) {
+  auto support_a =
+      CreateCompositorFrameSinkSupport(kFrameSinkIdA);  // Interactive
+  auto support_b = CreateCompositorFrameSinkSupport(kFrameSinkIdB);  // Captured
+
+  // Register B as captured.
+  manager_->OnCaptureStarted(kFrameSinkIdB);
+
+  // A interacts.
+  SubmitFrame(support_a.get(), true);
+
+  // A is interactive -> not throttled.
+  // B is captured -> not throttled (even though A is interacting).
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_a.get()));
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_b.get()));
+
+  manager_->OnCaptureStopped(kFrameSinkIdB);
+
+  // Now B should be throttled because A is still interacting.
+  EXPECT_EQ(base::Hertz(60) * 2, GetThrottleInterval(support_b.get()));
+}
+
+TEST_F(FrameSinkManagerPriorityTest, GlobalThrottlingWinsIfSlower) {
+  auto support_a = CreateCompositorFrameSinkSupport(kFrameSinkIdA);
+  auto support_b = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
+
+  // Global throttle to 10Hz (100ms).
+  manager_->StartThrottlingAllFrameSinks(base::Seconds(0.1));
+  EXPECT_EQ(base::Seconds(0.1), GetThrottleInterval(support_a.get()));
+  EXPECT_EQ(base::Seconds(0.1), GetThrottleInterval(support_b.get()));
+
+  // A interacts. Interaction implies 30Hz (33ms).
+  // 100ms > 33ms, so it should stay at 100ms.
+  SubmitFrame(support_a.get(), true);
+  EXPECT_EQ(base::Seconds(0.1), GetThrottleInterval(support_a.get()));
+  EXPECT_EQ(base::Seconds(0.1), GetThrottleInterval(support_b.get()));
+
+  // Interaction stops. Should still be 100ms due to global throttle.
+  SubmitFrame(support_a.get(), false);
+  EXPECT_EQ(base::Seconds(0.1), GetThrottleInterval(support_a.get()));
+  EXPECT_EQ(base::Seconds(0.1), GetThrottleInterval(support_b.get()));
+}
+
+TEST_F(FrameSinkManagerPriorityTest, ThrottlingUpdatedOnSinkDestruction) {
+  auto support_a = CreateCompositorFrameSinkSupport(kFrameSinkIdA);
+  auto support_b = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
+
+  // A interacts. B throttled.
+  SubmitFrame(support_a.get(), true);
+  EXPECT_EQ(base::Hertz(60) * 2, GetThrottleInterval(support_b.get()));
+
+  // Destroy A. Interaction should stop and B should no longer be throttled.
+  support_a.reset();
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_b.get()));
+}
+
+TEST_F(FrameSinkManagerPriorityTest, MultipleCapturedSinks) {
+  auto support_a = CreateCompositorFrameSinkSupport(kFrameSinkIdA);
+  auto support_b = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
+  auto support_c = CreateCompositorFrameSinkSupport(kFrameSinkIdC);
+
+  manager_->OnCaptureStarted(kFrameSinkIdB);
+  manager_->OnCaptureStarted(kFrameSinkIdC);
+
+  // A interacts. B and C captured, so NOT throttled.
+  SubmitFrame(support_a.get(), true);
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_a.get()));
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_b.get()));
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_c.get()));
+
+  // Stop capturing B. It should become throttled.
+  manager_->OnCaptureStopped(kFrameSinkIdB);
+  EXPECT_EQ(base::Hertz(60) * 2, GetThrottleInterval(support_b.get()));
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_c.get()));
+}
+
+TEST_F(FrameSinkManagerPriorityTest, ThrottleParentsOfInteractiveFrameSinks) {
+  auto support_parent = CreateCompositorFrameSinkSupport(kFrameSinkIdA);
+  auto support_child = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
+  auto support_other = CreateCompositorFrameSinkSupport(kFrameSinkIdC);
+
+  // Register A as parent of B.
+  manager_->RegisterFrameSinkHierarchy(kFrameSinkIdA, kFrameSinkIdB);
+
+  // B interacts.
+  SubmitFrame(support_child.get(), true);
+
+  // B is interactive -> not throttled.
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_child.get()));
+
+  // A is parent of interactive sink -> throttled.
+  EXPECT_EQ(base::Hertz(60) * 2, GetThrottleInterval(support_parent.get()));
+
+  // C is unrelated -> throttled.
+  EXPECT_EQ(base::Hertz(60) * 2, GetThrottleInterval(support_other.get()));
+
+  // Stop interaction.
+  SubmitFrame(support_child.get(), false);
+
+  // All cleared.
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_child.get()));
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_parent.get()));
+  EXPECT_EQ(base::TimeDelta(), GetThrottleInterval(support_other.get()));
+}
+
+}  // namespace
+}  // namespace viz
diff --git a/components/viz/service/input/android_state_transfer_handler.cc b/components/viz/service/input/android_state_transfer_handler.cc
index 542bf8dc..a068b32 100644
--- a/components/viz/service/input/android_state_transfer_handler.cc
+++ b/components/viz/service/input/android_state_transfer_handler.cc
@@ -393,7 +393,7 @@
   auto event = ui::MotionEventAndroidFactory::CreateFromNative(
       std::move(input_event),
       1.f / state_for_curr_sequence_->transfer_state->dip_scale,
-      state_for_curr_sequence_->transfer_state->web_contents_y_offset_pix,
+      state_for_curr_sequence_->transfer_state->web_contents_offset,
       event_times);
 
   state_for_curr_sequence_->rir_support->OnTouchEvent(
diff --git a/components/viz/service/input/android_state_transfer_handler_unittest.cc b/components/viz/service/input/android_state_transfer_handler_unittest.cc
index 31ca60ee..a59ec60 100644
--- a/components/viz/service/input/android_state_transfer_handler_unittest.cc
+++ b/components/viz/service/input/android_state_transfer_handler_unittest.cc
@@ -14,6 +14,7 @@
 #include "components/viz/service/input/viz_touch_state_handler.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/point_f.h"
 
 // Must come after all headers that specialize FromJniType() / ToJniType().
 #include "ui/events/motionevent_jni_headers/MotionEvent_jni.h"
@@ -480,33 +481,34 @@
   }
 }
 
-//  _______________________
-// | (sys_ui_offset)       |
-// |-----------------------|
-// | (web_contents_offset) |
-// |-----------------------|
-// |                       |
-// |                       |
-// |                       |
-// |                       |
-// |                       |
-// |                       |
-// |-----------------------|
-//
+//  _________________________
+// | (sys_ui_y_offset)       |
+// |-------------------------|
+// | (web_contents_y_offset) |
+// |-------------------------|
+// |web_     |               |
+// |contents_|               |
+// |x_offset |               |
+// |         |               |
+// |         |               |
+// |         |               |
+// |-------------------------|
 TEST_F(AndroidStateTransferHandlerTest,
        UsesWebContentsOffsetForMotionEventCreation) {
-  int sys_ui_offset = -9;
-  const int web_contents_offset = -8;
+  int sys_ui_x_offset = -7;
+  int sys_ui_y_offset = -9;
+  const int web_contents_x_offset = -6;
+  const int web_contents_y_offset = -8;
+  const int raw_x = 107;
   const int raw_y = 109;
-  const int delta_x = 0;
   const int meta_state = 0;
 
   JNIEnv* env = base::android::AttachCurrentThread();
   base::android::ScopedJavaLocalRef<jobject> java_motion_event =
-      JNI_MotionEvent::Java_MotionEvent_obtain(env, 0, 0, kAndroidActionDown, 0,
-                                               raw_y, meta_state);
-  JNI_MotionEvent::Java_MotionEvent_offsetLocation(env, java_motion_event,
-                                                   delta_x, sys_ui_offset);
+      JNI_MotionEvent::Java_MotionEvent_obtain(env, 0, 0, kAndroidActionDown,
+                                               raw_x, raw_y, meta_state);
+  JNI_MotionEvent::Java_MotionEvent_offsetLocation(
+      env, java_motion_event, sys_ui_x_offset, sys_ui_y_offset);
 
   const AInputEvent* native_event = nullptr;
   if (__builtin_available(android 31, *)) {
@@ -516,25 +518,30 @@
 
   auto state = input::mojom::TouchTransferState::New();
   state->dip_scale = 1.f;
-  state->web_contents_y_offset_pix = web_contents_offset;
+  state->web_contents_offset =
+      gfx::PointF(web_contents_x_offset, web_contents_y_offset);
 
   handler_.StateOnTouchTransfer(std::move(state),
                                 mock_rir_support_.GetWeakPtr());
 
-  int expected_y = raw_y + sys_ui_offset + web_contents_offset;
-  EXPECT_CALL(mock_rir_support_, OnTouchEvent(EqXYInPixels(0, expected_y), _));
+  int expected_x = raw_x + sys_ui_x_offset + web_contents_x_offset;
+  int expected_y = raw_y + sys_ui_y_offset + web_contents_y_offset;
+  EXPECT_CALL(mock_rir_support_,
+              OnTouchEvent(EqXYInPixels(expected_x, expected_y), _));
   handler_.OnMotionEvent(base::android::ScopedInputEvent(native_event),
                          kRootCompositorFrameSinkId);
 
-  // Offset by an arbitrary value which is larger than absolute value of
-  // `web_contents_offset`.
-  sys_ui_offset -= 10;
+  // Offset by arbitrary values which are larger than absolute values of
+  // `web_contents_x_offset` and `web_contents_y_offset`.
+  sys_ui_x_offset -= 10;
+  sys_ui_y_offset -= 10;
   base::android::ScopedJavaLocalRef<jobject>
       motion_event_with_diff_sys_ui_offset =
           JNI_MotionEvent::Java_MotionEvent_obtain(
-              env, 0, 0, kAndroidActionMove, 0, raw_y, meta_state);
+              env, 0, 0, kAndroidActionMove, raw_x, raw_y, meta_state);
   JNI_MotionEvent::Java_MotionEvent_offsetLocation(
-      env, motion_event_with_diff_sys_ui_offset, delta_x, sys_ui_offset);
+      env, motion_event_with_diff_sys_ui_offset, sys_ui_x_offset,
+      sys_ui_y_offset);
 
   if (__builtin_available(android 31, *)) {
     native_event =
@@ -542,8 +549,10 @@
   }
   CHECK(native_event);
 
-  expected_y = raw_y + sys_ui_offset + web_contents_offset;
-  EXPECT_CALL(mock_rir_support_, OnTouchEvent(EqXYInPixels(0, expected_y), _));
+  expected_x = raw_x + sys_ui_x_offset + web_contents_x_offset;
+  expected_y = raw_y + sys_ui_y_offset + web_contents_y_offset;
+  EXPECT_CALL(mock_rir_support_,
+              OnTouchEvent(EqXYInPixels(expected_x, expected_y), _));
   handler_.OnMotionEvent(base::android::ScopedInputEvent(native_event),
                          kRootCompositorFrameSinkId);
 }
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc
index 076ff28..4661225 100644
--- a/content/browser/accessibility/browser_accessibility_android.cc
+++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -522,23 +522,6 @@
   // children of a link as not interesting to prevent double utterances.
   const BrowserAccessibility* parent = PlatformGetParent();
 
-  // When SelectMobileDesktopParity is enabled, ListBox selects are supported on
-  // android in addition to combobox/MenuList selects, in which case ListBox
-  // options should be interesting or else they can't be selected or toggled.
-  if (!base::FeatureList::IsEnabled(
-          blink::features::kSelectMobileDesktopParity)) {
-    // Should not read options in a multiselect combobox as it is invisible.
-    // Adding IsFocusable() to handle an edge case in crbug.com/395134019 to
-    // allow select options in aria list box. This is also able to handle edge
-    // case in crbug.com/358195473 to not allow TalkBack to read out collapsed
-    // multi-selectable options.
-    if (parent && parent->GetRole() == ax::mojom::Role::kListBox &&
-        parent->HasState(ax::mojom::State::kMultiselectable) &&
-        GetRole() == ax::mojom::Role::kListBoxOption && IsFocusable()) {
-      return false;
-    }
-  }
-
   while (parent) {
     // Generally, if a parent is a control (like a combobox) and the child isn't
     // focusable, the child is hidden to reduce clutter.
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc
index c22f594..fcc2a393 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -510,8 +510,10 @@
     case ui::AXEventGenerator::Event::FOCUS_CHANGED:
     case ui::AXEventGenerator::Event::FLOW_FROM_CHANGED:
     case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
+    case ui::AXEventGenerator::Event::GRAMMAR_MARKER_CHANGED:
     case ui::AXEventGenerator::Event::HASPOPUP_CHANGED:
     case ui::AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
+    case ui::AXEventGenerator::Event::HIGHLIGHT_MARKER_CHANGED:
     case ui::AXEventGenerator::Event::IGNORED_CHANGED:
     case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
     case ui::AXEventGenerator::Event::KEY_SHORTCUTS_CHANGED:
@@ -542,6 +544,7 @@
     case ui::AXEventGenerator::Event::SELECTED_CHILDREN_CHANGED:
     case ui::AXEventGenerator::Event::SELECTED_VALUE_CHANGED:
     case ui::AXEventGenerator::Event::SET_SIZE_CHANGED:
+    case ui::AXEventGenerator::Event::SPELLING_MARKER_CHANGED:
     case ui::AXEventGenerator::Event::STATE_CHANGED:
     case ui::AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
     case ui::AXEventGenerator::Event::TEXT_SELECTION_CHANGED:
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index 1c69e7b..94f4d97 100644
--- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -854,9 +854,6 @@
 
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
                        AccessibilitySelectListboxActivateOptions) {
-  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kEnableBlinkFeatures,
-      blink::features::kSelectMobileDesktopParity.name);
   RunEventTest(FILE_PATH_LITERAL("select-multiple-activate-options.html"));
 }
 
@@ -1381,6 +1378,24 @@
   RunEventTest(FILE_PATH_LITERAL("delete-subtree.html"));
 }
 
+// TODO(crbug.com/487613492): Disabled due to ghost UIA COM refs on Windows bots.
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+                       DISABLED_AccessibilityEventsCssHighlightSpellingError) {
+  RunEventTest(FILE_PATH_LITERAL("css-highlight-spelling-error.html"));
+}
+
+// TODO(crbug.com/487613492): Disabled due to ghost UIA COM refs on Windows bots.
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+                       DISABLED_AccessibilityEventsCssHighlightGrammarError) {
+  RunEventTest(FILE_PATH_LITERAL("css-highlight-grammar-error.html"));
+}
+
+// TODO(crbug.com/487613492): Disabled due to ghost UIA COM refs on Windows bots.
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+                       DISABLED_AccessibilityEventsCssHighlightAdded) {
+  RunEventTest(FILE_PATH_LITERAL("css-highlight-added.html"));
+}
+
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsWithExperimentalWebFeaturesTest,
                        CarouselWithTabs) {
   RunEventTest(FILE_PATH_LITERAL("carousel-with-tabs.html"));
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 02db8fb..527545a 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -2269,9 +2269,6 @@
 
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
                        AccessibilitySelectListboxActivateOptions) {
-  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kEnableBlinkFeatures,
-      blink::features::kSelectMobileDesktopParity.name);
   RunHtmlTest(FILE_PATH_LITERAL("select-multiple-activate-options.html"));
 }
 
@@ -3724,9 +3721,6 @@
 
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
                        AccessibilitySelectListboxModes) {
-  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kEnableBlinkFeatures,
-      blink::features::kSelectMobileDesktopParity.name);
   RunHtmlTest(FILE_PATH_LITERAL("select-listbox-modes.html"));
 }
 
diff --git a/content/browser/ai/echo_ai_language_model.cc b/content/browser/ai/echo_ai_language_model.cc
index 213e98507..3bccc96 100644
--- a/content/browser/ai/echo_ai_language_model.cc
+++ b/content/browser/ai/echo_ai_language_model.cc
@@ -49,16 +49,16 @@
     return;
   }
 
-  uint32_t quota = EchoAIManagerImpl::kMaxContextSizeInTokens;
-  if (input.size() > quota) {
+  uint32_t context_window = EchoAIManagerImpl::kMaxContextSizeInTokens;
+  if (input.size() > context_window) {
     responder->OnError(
         blink::mojom::ModelStreamingResponseStatus::kErrorInputTooLarge,
-        blink::mojom::QuotaErrorInfo::New(input.size(), quota));
+        blink::mojom::QuotaErrorInfo::New(input.size(), context_window));
     return;
   }
-  if (current_tokens_ > quota - input.size()) {
+  if (current_tokens_ > context_window - input.size()) {
     current_tokens_ = input.size();
-    responder->OnQuotaOverflow();
+    responder->OnContextOverflow();
   }
   current_tokens_ += input.size();
   responder->OnStreaming(kResponsePrefix);
diff --git a/content/browser/devtools/protocol/input_handler.cc b/content/browser/devtools/protocol/input_handler.cc
index 0e9590b..455e5d6e1 100644
--- a/content/browser/devtools/protocol/input_handler.cc
+++ b/content/browser/devtools/protocol/input_handler.cc
@@ -1116,8 +1116,8 @@
 
   if (ignore_input_events_ && old_web_contents != web_contents_) {
     if (web_contents_) {
-      scoped_ignore_input_events_ =
-          web_contents_->IgnoreInputEvents(std::nullopt);
+      scoped_ignore_input_events_ = web_contents_->IgnoreInputEvents(
+          std::nullopt, /*should_ignore_a11y_input=*/true);
     } else {
       scoped_ignore_input_events_.reset();
     }
diff --git a/content/browser/loader/connection_allowlist_browsertest.cc b/content/browser/loader/connection_allowlist_browsertest.cc
index 70564ad..081226c9 100644
--- a/content/browser/loader/connection_allowlist_browsertest.cc
+++ b/content/browser/loader/connection_allowlist_browsertest.cc
@@ -38,6 +38,8 @@
 
 namespace {
 constexpr char kSameOriginAllowlistedPage[] = "/response_origin.html";
+constexpr char kCrossOriginAllowlistedPage[] =
+    "/response_and_cross_origin.html";
 }
 
 struct ResponseEntry {
@@ -45,6 +47,9 @@
   absl::flat_hash_map<std::string, std::string> headers;
 };
 
+// TODO(crbug.com/486121443): Once the test flakiness due to the issue in
+// WebPrescientNetworkingImpl is resolved, add a test covering preconnect from
+// the link header response.
 class ConnectionAllowlistTest : public ContentBrowserTest {
  public:
   ConnectionAllowlistTest()
@@ -499,4 +504,52 @@
   EXPECT_EQ(connection_tracker.GetAcceptedSocketCount(), 0u);
 }
 
+IN_PROC_BROWSER_TEST_F(ConnectionAllowlistTest, LinkPreconnect) {
+  // Create a separate server for receiving preconnect.
+  net::test_server::EmbeddedTestServer cross_origin_server;
+  net::test_server::ConnectionTracker connection_tracker(&cross_origin_server);
+
+  // Note: the URL pattern in allowlist should be surrounded by double quotes.
+  RegisterResponse(kCrossOriginAllowlistedPage,
+                   ResponseEntry("<html><body>Hello</body></html>",
+                                 {{"Connection-Allowlist",
+                                   R"((response-origin "*://b.test:*/*"))"}}));
+
+  // Use `StartAndReturnHandle()` to start the servers; this ensures graceful
+  // shutdown when the test finishes. Otherwise, a socket read may occur after
+  // the connection tracker is destroyed, invoking a callback via a dangling
+  // pointer and crashing the test.
+  auto cross_origin_server_handle = cross_origin_server.StartAndReturnHandle();
+  ASSERT_TRUE(cross_origin_server_handle);
+  auto server_handle = embedded_test_server()->StartAndReturnHandle();
+  ASSERT_TRUE(server_handle);
+
+  GURL allowed_url = cross_origin_server.GetURL("b.test", "/allow.js");
+  GURL denied_url = cross_origin_server.GetURL("c.test", "/deny.js");
+
+  EXPECT_TRUE(NavigateToURL(
+      shell(),
+      embedded_test_server()->GetURL("a.test", kCrossOriginAllowlistedPage)));
+
+  EXPECT_TRUE(
+      ExecJs(shell()->web_contents(), JsReplace(R"(
+            var allowed_link = document.createElement('link');
+            allowed_link.href = $1;
+            allowed_link.rel = 'preconnect';
+            allowed_link.crossorigin= 'anonymous';
+
+            var denied_link = document.createElement('link');
+            denied_link.href = $2;
+            denied_link.rel = 'preconnect';
+            denied_link.crossorigin= 'anonymous';
+
+            document.body.appendChild(allowed_link);
+            document.body.appendChild(denied_link);
+          )",
+                                                allowed_url, denied_url)));
+
+  connection_tracker.WaitForAcceptedConnections(1u);
+  EXPECT_EQ(1u, connection_tracker.GetAcceptedSocketCount());
+}
+
 }  // namespace content
diff --git a/content/browser/memory_coordinator/child_memory_consumer_registry_host.cc b/content/browser/memory_coordinator/child_memory_consumer_registry_host.cc
index 2145c6a..6161583 100644
--- a/content/browser/memory_coordinator/child_memory_consumer_registry_host.cc
+++ b/content/browser/memory_coordinator/child_memory_consumer_registry_host.cc
@@ -128,7 +128,7 @@
 
 void ChildMemoryConsumerRegistryHost::Register(
     const std::string& consumer_id,
-    base::MemoryConsumerTraits traits) {
+    std::optional<base::MemoryConsumerTraits> traits) {
   if (!coordinator_remote_.is_bound()) {
     mojo::ReportBadMessage("Register called before BindCoordinator");
     return;
diff --git a/content/browser/memory_coordinator/child_memory_consumer_registry_host.h b/content/browser/memory_coordinator/child_memory_consumer_registry_host.h
index a2b8ea93..38c1366 100644
--- a/content/browser/memory_coordinator/child_memory_consumer_registry_host.h
+++ b/content/browser/memory_coordinator/child_memory_consumer_registry_host.h
@@ -6,6 +6,7 @@
 #define CONTENT_BROWSER_MEMORY_COORDINATOR_CHILD_MEMORY_CONSUMER_REGISTRY_HOST_H_
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <string_view>
 
@@ -65,7 +66,7 @@
   void BindCoordinator(mojo::PendingRemote<mojom::ChildMemoryCoordinator>
                            coordinator_remote) override;
   void Register(const std::string& consumer_id,
-                base::MemoryConsumerTraits traits) override;
+                std::optional<base::MemoryConsumerTraits> traits) override;
   void Unregister(const std::string& consumer_id) override;
 
   // MemoryConsumerGroupHost:
diff --git a/content/browser/memory_coordinator/child_memory_consumer_registry_host_unittest.cc b/content/browser/memory_coordinator/child_memory_consumer_registry_host_unittest.cc
index 7e9c7537..985c523 100644
--- a/content/browser/memory_coordinator/child_memory_consumer_registry_host_unittest.cc
+++ b/content/browser/memory_coordinator/child_memory_consumer_registry_host_unittest.cc
@@ -5,6 +5,7 @@
 #include "content/browser/memory_coordinator/child_memory_consumer_registry_host.h"
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <string_view>
 #include <utility>
@@ -71,7 +72,7 @@
   MOCK_METHOD(void,
               OnConsumerGroupAdded,
               (std::string_view consumer_id,
-               base::MemoryConsumerTraits traits,
+               std::optional<base::MemoryConsumerTraits> traits,
                ProcessType process_type,
                ChildProcessId child_process_id),
               (override));
diff --git a/content/browser/navigation_transitions/back_forward_transition_animator.cc b/content/browser/navigation_transitions/back_forward_transition_animator.cc
index 31b5bb2..b0bc2f7 100644
--- a/content/browser/navigation_transitions/back_forward_transition_animator.cc
+++ b/content/browser/navigation_transitions/back_forward_transition_animator.cc
@@ -2108,7 +2108,8 @@
   ignore_input_scope_.emplace(animation_manager_->web_contents_view_android()
                                   ->web_contents()
                                   ->IgnoreInputEvents(
-                                      /*audit_callback=*/std::nullopt));
+                                      /*audit_callback=*/std::nullopt,
+                                      /*should_ignore_a11y_input=*/true));
 }
 
 void BackForwardTransitionAnimator::InsertLayersInOrder() {
diff --git a/content/browser/preloading/prerender/prerender_browsertest.cc b/content/browser/preloading/prerender/prerender_browsertest.cc
index 807160e..7446636c 100644
--- a/content/browser/preloading/prerender/prerender_browsertest.cc
+++ b/content/browser/preloading/prerender/prerender_browsertest.cc
@@ -15,7 +15,7 @@
 #include "base/feature_list.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/callback_helpers.h"
-#include "base/memory/memory_pressure_monitor.h"
+#include "base/memory/memory_pressure_listener_registry.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/metrics_hashes.h"
@@ -178,24 +178,6 @@
                                 ukm::SourceIdType::NAVIGATION_ID);
 }
 
-// A fake implementation of base::MemoryPressureMonitor. An instance of this
-// class is used via a global variable. The base class sets itself in the
-// global variable on the constructor and unsets it on the destructor.
-// base::MemoryPressureMonitor::Get() provides access to the instance.
-class FakeMemoryPressureMonitor : public base::MemoryPressureMonitor {
- public:
-  explicit FakeMemoryPressureMonitor(base::MemoryPressureLevel level)
-      : level_(level) {}
-
-  base::MemoryPressureLevel GetCurrentPressureLevel(
-      base::MemoryPressureMonitorTag tag) const override {
-    return level_;
-  }
-
- private:
-  const base::MemoryPressureLevel level_ = base::MEMORY_PRESSURE_LEVEL_NONE;
-};
-
 // Example class which inherits the DocumentUserData, all the data is
 // associated to the lifetime of the document.
 class DocumentData : public DocumentUserData<DocumentData> {
@@ -12135,11 +12117,8 @@
   ASSERT_TRUE(NavigateToURL(shell(), initial_url));
 
   // Emulate moderate-level memory pressure state.
-  FakeMemoryPressureMonitor memory_pressure_monitor(
+  base::MemoryPressureListenerRegistry::SimulatePressureNotification(
       base::MEMORY_PRESSURE_LEVEL_MODERATE);
-  ASSERT_EQ(base::MemoryPressureMonitor::Get()->GetCurrentPressureLevel(
-                base::MemoryPressureMonitorTag::kTest),
-            base::MEMORY_PRESSURE_LEVEL_MODERATE);
 
   // Triggering prerendering should not be canceled due to the moderate level
   // memory pressure.
@@ -12159,11 +12138,8 @@
   ASSERT_TRUE(NavigateToURL(shell(), initial_url));
 
   // Emulate critical-level memory pressure state.
-  FakeMemoryPressureMonitor memory_pressure_monitor(
+  base::MemoryPressureListenerRegistry::SimulatePressureNotification(
       base::MEMORY_PRESSURE_LEVEL_CRITICAL);
-  ASSERT_EQ(base::MemoryPressureMonitor::Get()->GetCurrentPressureLevel(
-                base::MemoryPressureMonitorTag::kTest),
-            base::MEMORY_PRESSURE_LEVEL_CRITICAL);
 
   // Triggering prerendering should be canceled due to the critical level memory
   // pressure.
diff --git a/content/browser/preloading/prerender/prerender_host_registry.cc b/content/browser/preloading/prerender/prerender_host_registry.cc
index 69d0945..89a57811 100644
--- a/content/browser/preloading/prerender/prerender_host_registry.cc
+++ b/content/browser/preloading/prerender/prerender_host_registry.cc
@@ -96,21 +96,6 @@
   return base::SysInfo::AmountOfPhysicalMemory().InMiB() > memory_threshold_mb;
 }
 
-base::MemoryPressureLevel GetCurrentMemoryPressureLevel() {
-  // Ignore the memory pressure event if the memory control is disabled.
-  if (!base::FeatureList::IsEnabled(
-          blink::features::kPrerender2MemoryControls)) {
-    return base::MEMORY_PRESSURE_LEVEL_NONE;
-  }
-
-  auto* monitor = base::MemoryPressureMonitor::Get();
-  if (!monitor) {
-    return base::MEMORY_PRESSURE_LEVEL_NONE;
-  }
-  return monitor->GetCurrentPressureLevel(
-      base::MemoryPressureMonitorTag::kPrerenderHostRegistry);
-}
-
 // Create a resource request for `back_url` that only checks whether the
 // resource is in the HTTP cache.
 std::unique_ptr<network::SimpleURLLoader> CreateHttpCacheQueryingResourceLoad(
@@ -1983,6 +1968,17 @@
              : base::SingleThreadTaskRunner::GetCurrentDefault();
 }
 
+base::MemoryPressureLevel
+PrerenderHostRegistry::GetCurrentMemoryPressureLevel() {
+  // Ignore the memory pressure event if the memory control is disabled.
+  if (!base::FeatureList::IsEnabled(
+          blink::features::kPrerender2MemoryControls)) {
+    return base::MEMORY_PRESSURE_LEVEL_NONE;
+  }
+
+  return memory_pressure_level();
+}
+
 void PrerenderHostRegistry::SetTaskRunnerForTesting(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
   timer_task_runner_for_testing_ = std::move(task_runner);
diff --git a/content/browser/preloading/prerender/prerender_host_registry.h b/content/browser/preloading/prerender/prerender_host_registry.h
index b01594b..4564a498 100644
--- a/content/browser/preloading/prerender/prerender_host_registry.h
+++ b/content/browser/preloading/prerender/prerender_host_registry.h
@@ -369,6 +369,8 @@
 
   scoped_refptr<base::SingleThreadTaskRunner> GetTimerTaskRunner();
 
+  base::MemoryPressureLevel GetCurrentMemoryPressureLevel();
+
   // Holds the PrerenderHostId of running PrerenderHost. Reset to an invalid
   // value when there's no running PrerenderHost. Tracks only the host id of
   // speculation rules triggers and ignores requests from embedder because
diff --git a/content/browser/renderer_host/render_widget_host_delegate.cc b/content/browser/renderer_host/render_widget_host_delegate.cc
index 74fea36..0311764 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.cc
+++ b/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -183,8 +183,8 @@
 }
 
 #if BUILDFLAG(IS_ANDROID)
-float RenderWidgetHostDelegate::GetCurrentTouchSequenceYOffset() {
-  return 0.f;
+gfx::PointF RenderWidgetHostDelegate::GetCurrentTouchSequenceOffset() {
+  return gfx::PointF();
 }
 #endif
 
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h
index 9fce41c5..4dad6bba 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -26,6 +26,7 @@
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
 #include "ui/base/mojom/window_show_state.mojom-forward.h"
 #include "ui/base/ui_base_types.h"
+#include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/mojom/delegated_ink_point_renderer.mojom.h"
 #include "ui/gfx/native_ui_types.h"
 
@@ -372,10 +373,9 @@
   virtual void OnInputIgnored(const blink::WebInputEvent& event) {}
 
 #if BUILDFLAG(IS_ANDROID)
-  // Get the y value by which the touch sequence is offsetted by. For e.g.
-  // visible top controls will result in a non zero offset to be added to touch
-  // events.
-  virtual float GetCurrentTouchSequenceYOffset();
+  // Get the offset for the current touch sequence. e.g. visible top controls or
+  // side UI will result in a nonzero offset being added to touch events.
+  virtual gfx::PointF GetCurrentTouchSequenceOffset();
 #endif
 
  protected:
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index fd7eb3e..802199c 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1420,8 +1420,8 @@
     return;
   }
 
-  const float y_offset_pix =
-      host()->delegate()->GetCurrentTouchSequenceYOffset();
+  const gfx::PointF web_contents_offset =
+      host()->delegate()->GetCurrentTouchSequenceOffset();
 
   std::optional<std::unique_ptr<ui::MotionEventAndroid>> motion_event_android =
       std::nullopt;
@@ -1431,7 +1431,7 @@
             gfx::PointF(event.GetX(0), event.GetY(0)));
   }
   remote->StateOnTouchTransfer(input::mojom::TouchTransferState::New(
-      event.GetRawDownTime(), GetFrameSinkId(), y_offset_pix,
+      event.GetRawDownTime(), GetFrameSinkId(), web_contents_offset,
       view_.GetDipScale(), browser_would_have_handled,
       std::move(motion_event_android)));
 }
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 2d36a74..62b142a 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -12133,9 +12133,9 @@
 }
 
 #if BUILDFLAG(IS_ANDROID)
-float WebContentsImpl::GetCurrentTouchSequenceYOffset() {
+gfx::PointF WebContentsImpl::GetCurrentTouchSequenceOffset() {
   ui::ViewAndroid* view_android = GetNativeView();
-  return view_android->event_forwarder()->GetCurrentTouchSequenceYOffset();
+  return view_android->event_forwarder()->GetCurrentTouchSequenceOffset();
 }
 #endif
 
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index af0e49f..581b6c62 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -1203,7 +1203,7 @@
       ui::Compositor* compositor) override;
   void OnInputIgnored(const blink::WebInputEvent& event) override;
 #if BUILDFLAG(IS_ANDROID)
-  float GetCurrentTouchSequenceYOffset() override;
+  gfx::PointF GetCurrentTouchSequenceOffset() override;
 #endif
 
   // RenderFrameHostManager::Delegate ------------------------------------------
diff --git a/content/child/memory_coordinator/browser_memory_coordinator_bridge.cc b/content/child/memory_coordinator/browser_memory_coordinator_bridge.cc
index bfe9298..2a0b80ee 100644
--- a/content/child/memory_coordinator/browser_memory_coordinator_bridge.cc
+++ b/content/child/memory_coordinator/browser_memory_coordinator_bridge.cc
@@ -21,7 +21,7 @@
 
 void BrowserMemoryCoordinatorBridge::OnConsumerGroupAdded(
     std::string_view consumer_id,
-    base::MemoryConsumerTraits traits,
+    std::optional<base::MemoryConsumerTraits> traits,
     ProcessType process_type,
     ChildProcessId child_process_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/content/child/memory_coordinator/browser_memory_coordinator_bridge.h b/content/child/memory_coordinator/browser_memory_coordinator_bridge.h
index 4f84792..fbac4bd 100644
--- a/content/child/memory_coordinator/browser_memory_coordinator_bridge.h
+++ b/content/child/memory_coordinator/browser_memory_coordinator_bridge.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_CHILD_MEMORY_COORDINATOR_BROWSER_MEMORY_COORDINATOR_BRIDGE_H_
 #define CONTENT_CHILD_MEMORY_COORDINATOR_BROWSER_MEMORY_COORDINATOR_BRIDGE_H_
 
+#include <optional>
 #include <string>
 #include <string_view>
 #include <vector>
@@ -42,7 +43,7 @@
 
   // MemoryCoordinatorPolicyManager::Observer:
   void OnConsumerGroupAdded(std::string_view consumer_id,
-                            base::MemoryConsumerTraits traits,
+                            std::optional<base::MemoryConsumerTraits> traits,
                             ProcessType process_type,
                             ChildProcessId child_process_id) override;
   void OnConsumerGroupRemoved(std::string_view consumer_id,
@@ -83,7 +84,8 @@
 #endif
 
   // Tracks all consumer groups known to this class.
-  absl::flat_hash_map<std::string, base::MemoryConsumerTraits> groups_;
+  absl::flat_hash_map<std::string, std::optional<base::MemoryConsumerTraits>>
+      groups_;
 
   SEQUENCE_CHECKER(sequence_checker_);
 };
diff --git a/content/child/memory_coordinator/browser_memory_coordinator_bridge_unittest.cc b/content/child/memory_coordinator/browser_memory_coordinator_bridge_unittest.cc
index e0d2e0fe..fc77b3b 100644
--- a/content/child/memory_coordinator/browser_memory_coordinator_bridge_unittest.cc
+++ b/content/child/memory_coordinator/browser_memory_coordinator_bridge_unittest.cc
@@ -44,7 +44,7 @@
   }
 
   void Register(const std::string& consumer_id,
-                base::MemoryConsumerTraits traits) override {
+                std::optional<base::MemoryConsumerTraits> traits) override {
     auto [_, inserted] = registered_ids_.insert(consumer_id);
     CHECK(inserted);
   }
@@ -67,7 +67,7 @@
   absl::flat_hash_set<std::string> registered_ids_;
 };
 
-const base::MemoryConsumerTraits kTestTraits1{};
+const std::optional<base::MemoryConsumerTraits> kTestTraits1 = std::nullopt;
 
 }  // namespace
 
diff --git a/content/child/memory_coordinator/child_memory_consumer_registry.h b/content/child/memory_coordinator/child_memory_consumer_registry.h
index d34e128..c10b13e 100644
--- a/content/child/memory_coordinator/child_memory_consumer_registry.h
+++ b/content/child/memory_coordinator/child_memory_consumer_registry.h
@@ -6,6 +6,7 @@
 #define CONTENT_CHILD_MEMORY_COORDINATOR_CHILD_MEMORY_CONSUMER_REGISTRY_H_
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <string_view>
 #include <vector>
@@ -44,7 +45,7 @@
   // identically.
   class ConsumerGroup {
    public:
-    explicit ConsumerGroup(base::MemoryConsumerTraits traits);
+    explicit ConsumerGroup(std::optional<base::MemoryConsumerTraits> traits);
 
     ~ConsumerGroup();
 
@@ -57,10 +58,10 @@
 
     bool empty() const { return memory_consumers_.empty(); }
 
-    base::MemoryConsumerTraits traits() const { return traits_; }
+    std::optional<base::MemoryConsumerTraits> traits() const { return traits_; }
 
    private:
-    base::MemoryConsumerTraits traits_;
+    std::optional<base::MemoryConsumerTraits> traits_;
 
     int memory_limit_ = base::MemoryConsumer::kDefaultMemoryLimit;
 
@@ -69,7 +70,7 @@
 
   // base::MemoryConsumerRegistry:
   void OnMemoryConsumerAdded(std::string_view consumer_id,
-                             base::MemoryConsumerTraits traits,
+                             std::optional<base::MemoryConsumerTraits> traits,
                              base::RegisteredMemoryConsumer consumer) override;
   void OnMemoryConsumerRemoved(
       std::string_view consumer_id,
diff --git a/content/child/memory_coordinator/child_memory_consumer_registry_unittest.cc b/content/child/memory_coordinator/child_memory_consumer_registry_unittest.cc
index c1ae2d3..26c47bac 100644
--- a/content/child/memory_coordinator/child_memory_consumer_registry_unittest.cc
+++ b/content/child/memory_coordinator/child_memory_consumer_registry_unittest.cc
@@ -5,6 +5,7 @@
 #include "content/child/memory_coordinator/child_memory_consumer_registry.h"
 
 #include <map>
+#include <optional>
 #include <string>
 #include <string_view>
 #include <vector>
@@ -28,13 +29,13 @@
 
 struct ConsumerEntry {
   std::string consumer_id;
-  base::MemoryConsumerTraits traits;
+  std::optional<base::MemoryConsumerTraits> traits;
   ProcessType process_type;
   ChildProcessId child_process_id;
   raw_ptr<MemoryConsumerGroupHost> host;
 };
 
-const base::MemoryConsumerTraits kTestTraits1{};
+const std::optional<base::MemoryConsumerTraits> kTestTraits1 = std::nullopt;
 
 }  // namespace
 
@@ -58,7 +59,7 @@
   }
 
   void OnConsumerGroupAdded(std::string_view consumer_id,
-                            base::MemoryConsumerTraits traits,
+                            std::optional<base::MemoryConsumerTraits> traits,
                             ProcessType process_type,
                             ChildProcessId child_process_id) override {
     entries_.push_back({std::string(consumer_id), traits, process_type,
diff --git a/content/common/memory_coordinator/memory_consumer_group_controller.h b/content/common/memory_coordinator/memory_consumer_group_controller.h
index 33d452b1..043ac6e 100644
--- a/content/common/memory_coordinator/memory_consumer_group_controller.h
+++ b/content/common/memory_coordinator/memory_consumer_group_controller.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_COMMON_MEMORY_COORDINATOR_MEMORY_CONSUMER_GROUP_CONTROLLER_H_
 #define CONTENT_COMMON_MEMORY_COORDINATOR_MEMORY_CONSUMER_GROUP_CONTROLLER_H_
 
+#include <optional>
 #include <string_view>
 
 #include "base/memory_coordinator/traits.h"
@@ -29,10 +30,11 @@
       ChildProcessId child_process_id) = 0;
 
   // Called when a new consumer group is added/removed to/from the host.
-  virtual void OnConsumerGroupAdded(std::string_view consumer_id,
-                                    base::MemoryConsumerTraits traits,
-                                    ProcessType process_type,
-                                    ChildProcessId child_process_id) = 0;
+  virtual void OnConsumerGroupAdded(
+      std::string_view consumer_id,
+      std::optional<base::MemoryConsumerTraits> traits,
+      ProcessType process_type,
+      ChildProcessId child_process_id) = 0;
   virtual void OnConsumerGroupRemoved(std::string_view consumer_id,
                                       ChildProcessId child_process_id) = 0;
 
diff --git a/content/common/memory_coordinator/memory_consumer_registry.cc b/content/common/memory_coordinator/memory_consumer_registry.cc
index b8e5689..968fe9a 100644
--- a/content/common/memory_coordinator/memory_consumer_registry.cc
+++ b/content/common/memory_coordinator/memory_consumer_registry.cc
@@ -15,7 +15,7 @@
 // MemoryConsumerRegistry::ConsumerGroup ---------------------------------------
 
 MemoryConsumerRegistry::ConsumerGroup::ConsumerGroup(
-    base::MemoryConsumerTraits traits)
+    std::optional<base::MemoryConsumerTraits> traits)
     : traits_(traits) {}
 
 MemoryConsumerRegistry::ConsumerGroup::~ConsumerGroup() {
@@ -87,7 +87,7 @@
 
 void MemoryConsumerRegistry::OnMemoryConsumerAdded(
     std::string_view consumer_id,
-    base::MemoryConsumerTraits traits,
+    std::optional<base::MemoryConsumerTraits> traits,
     base::RegisteredMemoryConsumer consumer) {
   auto [it, inserted] = consumer_groups_.try_emplace(consumer_id);
   std::unique_ptr<ConsumerGroup>& consumer_group = it->second;
diff --git a/content/common/memory_coordinator/memory_consumer_registry.h b/content/common/memory_coordinator/memory_consumer_registry.h
index 6b63129..866305e 100644
--- a/content/common/memory_coordinator/memory_consumer_registry.h
+++ b/content/common/memory_coordinator/memory_consumer_registry.h
@@ -6,6 +6,7 @@
 #define CONTENT_COMMON_MEMORY_COORDINATOR_MEMORY_CONSUMER_REGISTRY_H_
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <string_view>
 #include <vector>
@@ -43,7 +44,7 @@
   // identically.
   class ConsumerGroup {
    public:
-    explicit ConsumerGroup(base::MemoryConsumerTraits traits);
+    explicit ConsumerGroup(std::optional<base::MemoryConsumerTraits> traits);
 
     ~ConsumerGroup();
 
@@ -56,10 +57,10 @@
 
     bool empty() const { return memory_consumers_.empty(); }
 
-    base::MemoryConsumerTraits traits() const { return traits_; }
+    std::optional<base::MemoryConsumerTraits> traits() const { return traits_; }
 
    private:
-    base::MemoryConsumerTraits traits_;
+    std::optional<base::MemoryConsumerTraits> traits_;
 
     int memory_limit_ = base::MemoryConsumer::kDefaultMemoryLimit;
 
@@ -68,7 +69,7 @@
 
   // base::MemoryConsumerRegistry:
   void OnMemoryConsumerAdded(std::string_view consumer_id,
-                             base::MemoryConsumerTraits traits,
+                             std::optional<base::MemoryConsumerTraits> traits,
                              base::RegisteredMemoryConsumer consumer) override;
   void OnMemoryConsumerRemoved(
       std::string_view consumer_id,
diff --git a/content/common/memory_coordinator/memory_consumer_registry_unittest.cc b/content/common/memory_coordinator/memory_consumer_registry_unittest.cc
index 053d2fb..2421c1d9 100644
--- a/content/common/memory_coordinator/memory_consumer_registry_unittest.cc
+++ b/content/common/memory_coordinator/memory_consumer_registry_unittest.cc
@@ -5,6 +5,7 @@
 #include "content/common/memory_coordinator/memory_consumer_registry.h"
 
 #include <map>
+#include <optional>
 #include <string>
 #include <string_view>
 #include <vector>
@@ -29,13 +30,13 @@
 
 struct ConsumerEntry {
   std::string consumer_id;
-  base::MemoryConsumerTraits traits;
+  std::optional<base::MemoryConsumerTraits> traits;
   ProcessType process_type;
   ChildProcessId child_process_id;
   raw_ptr<MemoryConsumerGroupHost> host;
 };
 
-const base::MemoryConsumerTraits kTestTraits1{};
+const std::optional<base::MemoryConsumerTraits> kTestTraits1 = std::nullopt;
 
 }  // namespace
 
@@ -62,7 +63,7 @@
   }
 
   void OnConsumerGroupAdded(std::string_view consumer_id,
-                            base::MemoryConsumerTraits traits,
+                            std::optional<base::MemoryConsumerTraits> traits,
                             ProcessType process_type,
                             ChildProcessId child_process_id) override {
     entries_.push_back({std::string(consumer_id), traits, process_type,
diff --git a/content/common/memory_coordinator/memory_coordinator_policy_manager.cc b/content/common/memory_coordinator/memory_coordinator_policy_manager.cc
index 2eec674..1fdcd53 100644
--- a/content/common/memory_coordinator/memory_coordinator_policy_manager.cc
+++ b/content/common/memory_coordinator/memory_coordinator_policy_manager.cc
@@ -17,7 +17,7 @@
 // MemoryCoordinatorPolicyManager::GroupState ----------------------------------
 
 MemoryCoordinatorPolicyManager::GroupState::GroupState(
-    base::MemoryConsumerTraits traits,
+    std::optional<base::MemoryConsumerTraits> traits,
     ProcessType process_type)
     : traits_(traits), process_type_(process_type) {}
 
@@ -170,7 +170,7 @@
 
 void MemoryCoordinatorPolicyManager::OnConsumerGroupAdded(
     std::string_view consumer_id,
-    base::MemoryConsumerTraits traits,
+    std::optional<base::MemoryConsumerTraits> traits,
     ProcessType process_type,
     ChildProcessId child_process_id) {
   HostState& host_state = GetHostState(child_process_id);
diff --git a/content/common/memory_coordinator/memory_coordinator_policy_manager.h b/content/common/memory_coordinator/memory_coordinator_policy_manager.h
index a565034..875ae47 100644
--- a/content/common/memory_coordinator/memory_coordinator_policy_manager.h
+++ b/content/common/memory_coordinator/memory_coordinator_policy_manager.h
@@ -6,6 +6,7 @@
 #define CONTENT_COMMON_MEMORY_COORDINATOR_MEMORY_COORDINATOR_POLICY_MANAGER_H_
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <string_view>
 
@@ -47,10 +48,11 @@
     ~Observer() override = default;
 
     // Called when a new consumer group is added/removed.
-    virtual void OnConsumerGroupAdded(std::string_view consumer_id,
-                                      base::MemoryConsumerTraits traits,
-                                      ProcessType process_type,
-                                      ChildProcessId child_process_id) = 0;
+    virtual void OnConsumerGroupAdded(
+        std::string_view consumer_id,
+        std::optional<base::MemoryConsumerTraits> traits,
+        ProcessType process_type,
+        ChildProcessId child_process_id) = 0;
     virtual void OnConsumerGroupRemoved(std::string_view consumer_id,
                                         ChildProcessId child_process_id) = 0;
   };
@@ -101,7 +103,7 @@
                                   MemoryConsumerGroupHost* host) override;
   void RemoveMemoryConsumerGroupHost(ChildProcessId child_process_id) override;
   void OnConsumerGroupAdded(std::string_view consumer_id,
-                            base::MemoryConsumerTraits traits,
+                            std::optional<base::MemoryConsumerTraits> traits,
                             ProcessType process_type,
                             ChildProcessId child_process_id) override;
   void OnConsumerGroupRemoved(std::string_view consumer_id,
@@ -124,7 +126,7 @@
 
   using ConsumerFilter =
       base::FunctionRef<bool(std::string_view consumer_id,
-                             base::MemoryConsumerTraits traits,
+                             std::optional<base::MemoryConsumerTraits> traits,
                              ProcessType process_type,
                              ChildProcessId child_process_id)>;
 
@@ -142,7 +144,8 @@
  private:
   class GroupState {
    public:
-    GroupState(base::MemoryConsumerTraits traits, ProcessType process_type);
+    GroupState(std::optional<base::MemoryConsumerTraits> traits,
+               ProcessType process_type);
     ~GroupState();
 
     // Updates the limit requested by `policy`. Returns the new aggregate limit
@@ -155,7 +158,7 @@
     std::optional<int> ClearMemoryLimitForPolicy(
         MemoryCoordinatorPolicy* policy);
 
-    base::MemoryConsumerTraits traits() const { return traits_; }
+    std::optional<base::MemoryConsumerTraits> traits() const { return traits_; }
     ProcessType process_type() const { return process_type_; }
     int current_limit() const { return current_limit_; }
 
@@ -165,7 +168,7 @@
     // Computes the memory limit based on existing policies.
     int RecomputeMemoryLimit() const;
 
-    const base::MemoryConsumerTraits traits_;
+    const std::optional<base::MemoryConsumerTraits> traits_;
     const ProcessType process_type_;
 
     // The limit requested by each policy.
diff --git a/content/common/memory_coordinator/memory_coordinator_policy_manager_unittest.cc b/content/common/memory_coordinator/memory_coordinator_policy_manager_unittest.cc
index 5c93948..fc72533 100644
--- a/content/common/memory_coordinator/memory_coordinator_policy_manager_unittest.cc
+++ b/content/common/memory_coordinator/memory_coordinator_policy_manager_unittest.cc
@@ -5,6 +5,7 @@
 #include "content/common/memory_coordinator/memory_coordinator_policy_manager.h"
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <string_view>
 #include <utility>
@@ -286,10 +287,12 @@
 
   policy.manager().UpdateConsumers(
       &policy,
-      [](std::string_view consumer_id, base::MemoryConsumerTraits traits,
+      [](std::string_view consumer_id,
+         std::optional<base::MemoryConsumerTraits> traits,
          ProcessType process_type, ChildProcessId child_process_id) {
-        return traits.supports_memory_limit ==
-               base::MemoryConsumerTraits::SupportsMemoryLimit::kYes;
+        return traits.has_value() &&
+               traits->supports_memory_limit ==
+                   base::MemoryConsumerTraits::SupportsMemoryLimit::kYes;
       },
       50, true);
 
@@ -314,7 +317,7 @@
   MOCK_METHOD(void,
               OnConsumerGroupAdded,
               (std::string_view consumer_id,
-               base::MemoryConsumerTraits traits,
+               std::optional<base::MemoryConsumerTraits> traits,
                ProcessType process_type,
                ChildProcessId child_process_id),
               (override));
@@ -354,7 +357,8 @@
 
   static constexpr char kConsumerId[] = "consumer";
 
-  EXPECT_CALL(policy, OnConsumerGroupAdded(kConsumerId, kTestTraits1,
+  EXPECT_CALL(policy, OnConsumerGroupAdded(kConsumerId,
+                                           std::make_optional(kTestTraits1),
                                            PROCESS_TYPE_RENDERER, kChildId));
   policy_manager().OnConsumerGroupAdded(kConsumerId, kTestTraits1,
                                         PROCESS_TYPE_RENDERER, kChildId);
@@ -382,7 +386,8 @@
   MockObserverPolicy policy(policy_manager());
 
   // Adding the policy should trigger notification of the existing group.
-  EXPECT_CALL(policy, OnConsumerGroupAdded(kConsumerId, kTestTraits1,
+  EXPECT_CALL(policy, OnConsumerGroupAdded(kConsumerId,
+                                           std::make_optional(kTestTraits1),
                                            PROCESS_TYPE_RENDERER, kChildId));
   MemoryCoordinatorPolicyRegistration registration(policy_manager(), policy);
   Mock::VerifyAndClearExpectations(&policy);
diff --git a/content/common/memory_coordinator/memory_pressure_listener_policy.cc b/content/common/memory_coordinator/memory_pressure_listener_policy.cc
index 6803ca33..647cd09 100644
--- a/content/common/memory_coordinator/memory_pressure_listener_policy.cc
+++ b/content/common/memory_coordinator/memory_pressure_listener_policy.cc
@@ -4,6 +4,8 @@
 
 #include "content/common/memory_coordinator/memory_pressure_listener_policy.h"
 
+#include <optional>
+
 #include "base/memory/memory_pressure_listener.h"
 #include "content/common/memory_coordinator/memory_coordinator_policy_manager.h"
 #include "content/public/common/child_process_id.h"
@@ -30,7 +32,8 @@
 
   manager().UpdateConsumers(
       this,
-      [](std::string_view consumer_id, base::MemoryConsumerTraits traits,
+      [](std::string_view consumer_id,
+         std::optional<base::MemoryConsumerTraits> traits,
          ProcessType process_type, ChildProcessId child_process_id) {
         return child_process_id.is_null();
       },
diff --git a/content/common/memory_coordinator/mojom/memory_coordinator.mojom b/content/common/memory_coordinator/mojom/memory_coordinator.mojom
index 22d5f7ea..df5356df 100644
--- a/content/common/memory_coordinator/mojom/memory_coordinator.mojom
+++ b/content/common/memory_coordinator/mojom/memory_coordinator.mojom
@@ -52,7 +52,7 @@
   BindCoordinator(pending_remote<ChildMemoryCoordinator> coordinator);
 
   // Registers a MemoryConsumer with the browser-side registry.
-  Register(string consumer_id, MemoryConsumerTraits traits);
+  Register(string consumer_id, MemoryConsumerTraits? traits);
 
   // Unregisters a MemoryConsumer with the browser-side registry.
   Unregister(string consumer_id);
diff --git a/content/public/android/junit/src/org/chromium/content/browser/SpareChildConnectionTest.java b/content/public/android/junit/src/org/chromium/content/browser/SpareChildConnectionTest.java
index 66cd826..3923add 100644
--- a/content/public/android/junit/src/org/chromium/content/browser/SpareChildConnectionTest.java
+++ b/content/public/android/junit/src/org/chromium/content/browser/SpareChildConnectionTest.java
@@ -21,10 +21,12 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.ChildBindingState;
@@ -104,9 +106,10 @@
 
     private SpareChildConnection mSpareConnection;
 
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
 
         // The tests run on only one thread. Pretend that is the launcher thread so LauncherThread
         // asserts are not triggered.
diff --git a/content/renderer/media/audio_decoder.cc b/content/renderer/media/audio_decoder.cc
index 5121ab98..bf0c1c3 100644
--- a/content/renderer/media/audio_decoder.cc
+++ b/content/renderer/media/audio_decoder.cc
@@ -68,7 +68,9 @@
   // Allocate and configure the output audio channel data and then
   // copy the decoded data to the destination.
   auto out = std::make_unique<WebAudioBus>();
-  out->Initialize(number_of_channels, number_of_frames, sample_rate);
+  if (!out->TryInitialize(number_of_channels, number_of_frames, sample_rate)) {
+    return nullptr;
+  }
 
   std::vector<base::SpanWriter<float>> dest_channels;
   dest_channels.reserve(number_of_channels);
diff --git a/content/renderer/memory_coordinator/renderer_memory_coordinator_policy.cc b/content/renderer/memory_coordinator/renderer_memory_coordinator_policy.cc
index 269688c8..dc40d6f 100644
--- a/content/renderer/memory_coordinator/renderer_memory_coordinator_policy.cc
+++ b/content/renderer/memory_coordinator/renderer_memory_coordinator_policy.cc
@@ -4,6 +4,7 @@
 
 #include "content/renderer/memory_coordinator/renderer_memory_coordinator_policy.h"
 
+#include <optional>
 #include <string>
 #include <string_view>
 
@@ -59,10 +60,12 @@
   // notify consumers that retain references to the v8 heap.
   manager().UpdateConsumers(
       this,
-      [](std::string_view consumer_id, base::MemoryConsumerTraits traits,
+      [](std::string_view consumer_id,
+         std::optional<base::MemoryConsumerTraits> traits,
          ProcessType process_type, ChildProcessId child_process_id) {
-        return traits.release_gc_references ==
-               base::MemoryConsumerTraits::ReleaseGCReferences::kYes;
+        return traits.has_value() &&
+               traits->release_gc_references ==
+                   base::MemoryConsumerTraits::ReleaseGCReferences::kYes;
       },
       0, /*release_memory=*/true);
 
@@ -81,10 +84,12 @@
 void RendererMemoryCoordinatorPolicy::OnRestoreLimitTimerFired() {
   manager().UpdateConsumers(
       this,
-      [](std::string_view consumer_id, base::MemoryConsumerTraits traits,
+      [](std::string_view consumer_id,
+         std::optional<base::MemoryConsumerTraits> traits,
          ProcessType process_type, ChildProcessId child_process_id) {
-        return traits.release_gc_references ==
-               base::MemoryConsumerTraits::ReleaseGCReferences::kYes;
+        return traits.has_value() &&
+               traits->release_gc_references ==
+                   base::MemoryConsumerTraits::ReleaseGCReferences::kYes;
       },
       base::MemoryConsumer::kDefaultMemoryLimit, /*release_memory=*/false);
 }
diff --git a/content/test/content_test_bundle_data.filelist b/content/test/content_test_bundle_data.filelist
index cf4f216f..af17353f 100644
--- a/content/test/content_test_bundle_data.filelist
+++ b/content/test/content_test_bundle_data.filelist
@@ -2663,6 +2663,12 @@
 data/accessibility/event/css-flex-text-update-expected-uia-win.txt
 data/accessibility/event/css-flex-text-update-expected-win.txt
 data/accessibility/event/css-flex-text-update.html
+data/accessibility/event/css-highlight-added-expected-uia-win.txt
+data/accessibility/event/css-highlight-added.html
+data/accessibility/event/css-highlight-grammar-error-expected-uia-win.txt
+data/accessibility/event/css-highlight-grammar-error.html
+data/accessibility/event/css-highlight-spelling-error-expected-uia-win.txt
+data/accessibility/event/css-highlight-spelling-error.html
 data/accessibility/event/css-visibility-collapse-expected-android.txt
 data/accessibility/event/css-visibility-collapse-expected-win.txt
 data/accessibility/event/css-visibility-collapse.html
diff --git a/content/test/data/accessibility/event/css-highlight-added-expected-uia-win.txt b/content/test/data/accessibility/event/css-highlight-added-expected-uia-win.txt
new file mode 100644
index 0000000..fa15764
--- /dev/null
+++ b/content/test/data/accessibility/event/css-highlight-added-expected-uia-win.txt
@@ -0,0 +1 @@
+Changes/AnnotationType_Highlighted on role=group, name=edit
diff --git a/content/test/data/accessibility/event/css-highlight-added.html b/content/test/data/accessibility/event/css-highlight-added.html
new file mode 100644
index 0000000..7a851fd
--- /dev/null
+++ b/content/test/data/accessibility/event/css-highlight-added.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="edit" contenteditable="true" aria-label="edit">Some text here</div>
+<script>
+  function go() {
+    const textNode = document.getElementById('edit').firstChild;
+    const range = new Range();
+    range.setStart(textNode, 0);
+    range.setEnd(textNode, 4);
+    const highlight = new Highlight(range);
+    CSS.highlights.set("test-highlight", highlight);
+  }
+</script>
+</body>
+</html>
diff --git a/content/test/data/accessibility/event/css-highlight-grammar-error-expected-uia-win.txt b/content/test/data/accessibility/event/css-highlight-grammar-error-expected-uia-win.txt
new file mode 100644
index 0000000..6bebc26
--- /dev/null
+++ b/content/test/data/accessibility/event/css-highlight-grammar-error-expected-uia-win.txt
@@ -0,0 +1 @@
+Changes/AnnotationType_GrammarError on role=group, name=edit
diff --git a/content/test/data/accessibility/event/css-highlight-grammar-error.html b/content/test/data/accessibility/event/css-highlight-grammar-error.html
new file mode 100644
index 0000000..8968bae
--- /dev/null
+++ b/content/test/data/accessibility/event/css-highlight-grammar-error.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="edit" contenteditable="true" aria-label="edit">Some text here</div>
+<script>
+  function go() {
+    const textNode = document.getElementById('edit').firstChild;
+    const range = new Range();
+    range.setStart(textNode, 0);
+    range.setEnd(textNode, 4);
+    const highlight = new Highlight(range);
+    highlight.type = "grammar-error";
+    CSS.highlights.set("test-grammar", highlight);
+  }
+</script>
+</body>
+</html>
diff --git a/content/test/data/accessibility/event/css-highlight-spelling-error-expected-uia-win.txt b/content/test/data/accessibility/event/css-highlight-spelling-error-expected-uia-win.txt
new file mode 100644
index 0000000..4e10423
--- /dev/null
+++ b/content/test/data/accessibility/event/css-highlight-spelling-error-expected-uia-win.txt
@@ -0,0 +1 @@
+Changes/AnnotationType_SpellingError on role=group, name=edit
diff --git a/content/test/data/accessibility/event/css-highlight-spelling-error.html b/content/test/data/accessibility/event/css-highlight-spelling-error.html
new file mode 100644
index 0000000..3a270d2
--- /dev/null
+++ b/content/test/data/accessibility/event/css-highlight-spelling-error.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="edit" contenteditable="true" aria-label="edit">Some text here</div>
+<script>
+  function go() {
+    const textNode = document.getElementById('edit').firstChild;
+    const range = new Range();
+    range.setStart(textNode, 0);
+    range.setEnd(textNode, 4);
+    const highlight = new Highlight(range);
+    highlight.type = "spelling-error";
+    CSS.highlights.set("test-spelling", highlight);
+  }
+</script>
+</body>
+</html>
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index 9884c95..c398d33 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -293,10 +293,6 @@
 # point. This is for things like tests that fail in a way that negatively and
 # significantly impacts other tests, e.g. killing the test device.
 
-# Skipped while noncoherent support is being added to PLS
-# NOTE: re-enable all suppressions for this test below when removing this line!
-crbug.com/angleproject/40096838 conformance2/extensions/webgl-shader-pixel-local-storage.html [ Skip ]
-
 # Skipped because EXT_disjoint_timer_query was disabled due to security concerns.
 crbug.com/808744 [ android ] WebglExtension_EXT_disjoint_timer_query_webgl2 [ Skip ]
 
@@ -513,6 +509,19 @@
 # Conformance expectations
 # ========================
 
+# Shader translator needs to be revised
+crbug.com/486945330 conformance/glsl/misc/shader-with-double-underscore.html [ Failure ]
+
+# Verification of zero-sized SVGs needs to be changed
+crbug.com/487208470 conformance/textures/misc/tex-image-svg-image-no-natural-width-and-height.html [ Failure ]
+
+# getUniformLocation validation was made more stringent
+crbug.com/487128732 conformance/uniforms/gl-get-uniform-location-errors.html [ Failure ]
+
+# Failing new ASTC offset tests on multiple Android devices
+crbug.com/487128735 [ android android-pixel-2 passthrough ] conformance/extensions/webgl-compressed-texture-astc.html [ Failure ]
+crbug.com/487128735 [ android android-pixel-4 passthrough ] conformance/extensions/webgl-compressed-texture-astc.html [ Failure ]
+
 # Test needs to be revised for new mipmap/texture completeness rules.
 crbug.com/angleproject/42267266 [ passthrough ] conformance2/textures/misc/immutable-tex-render-feedback.html [ Failure ]
 
@@ -612,8 +621,7 @@
 
 # Win / Snapdragon X Elite / D3D11
 crbug.com/41496016 [ win11 qualcomm-0x36334330 angle-d3d11 ] conformance/textures/misc/mipmap-fbo.html [ Failure ]
-# TODO(crbug.com/angleproject/40096838): re-enable
-# crbug.com/41496016 [ win11 qualcomm-0x36334330 angle-d3d11 graphite-disabled ] conformance2/extensions/webgl-shader-pixel-local-storage.html [ Failure ]
+crbug.com/41496016 [ win11 qualcomm-0x36334330 angle-d3d11 graphite-disabled ] conformance2/extensions/webgl-shader-pixel-local-storage.html [ Failure ]
 crbug.com/41496016 [ win11 qualcomm-0x36334330 angle-d3d11 ] deqp/functional/gles3/shadertexturefunction/texelfetchoffset.html [ Failure ]
 crbug.com/41496274 [ win11 qualcomm-0x36334330 angle-d3d11 ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_lines.html [ Failure ]
 crbug.com/41496274 [ win11 qualcomm-0x36334330 angle-d3d11 ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_points.html [ Failure ]
@@ -634,8 +642,7 @@
 crbug.com/41496274 [ win11 qualcomm-0x36334330 angle-d3d11 ] deqp/functional/gles3/transformfeedback/random_separate_triangles.html [ Failure ]
 
 # Graphite
-# TODO(crbug.com/angleproject/40096838): re-enable
-# crbug.com/332745399 [ win graphite-enabled ] conformance2/extensions/webgl-shader-pixel-local-storage.html [ Failure ]
+crbug.com/332745399 [ win graphite-enabled ] conformance2/extensions/webgl-shader-pixel-local-storage.html [ Failure ]
 
 # Win11 Qualcomm
 crbug.com/476376945 [ win11 qualcomm-0x41333430 angle-d3d11 ] conformance2/rendering/framebuffer-render-to-layer.html [ Failure ]
@@ -910,8 +917,7 @@
 crbug.com/446941342 [ android android-pixel-10 passthrough ] conformance2/extensions/ext-texture-norm16.html [ Failure ]
 crbug.com/446941342 [ android android-pixel-10 ] conformance2/extensions/oes-sample-variables.html [ Failure ]
 crbug.com/446941342 [ android android-pixel-10 ] conformance2/extensions/webgl-blend-func-extended.html [ Failure ]
-# TODO(crbug.com/angleproject/40096838): re-enable
-# crbug.com/446941342 [ android android-pixel-10 ] conformance2/extensions/webgl-shader-pixel-local-storage.html [ Failure ]
+crbug.com/446941342 [ android android-pixel-10 ] conformance2/extensions/webgl-shader-pixel-local-storage.html [ Failure ]
 crbug.com/446941342 [ android android-pixel-10 ] conformance2/glsl3/array-complex-indexing.html [ Failure ]
 crbug.com/446941342 [ android android-pixel-10 ] conformance2/glsl3/loops-with-side-effects.html [ Failure ]
 crbug.com/446941342 [ android android-pixel-10 ] conformance2/glsl3/tricky-loop-conditions.html [ Failure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index b10fc9520..cc53388 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -392,6 +392,19 @@
 # Conformance expectations
 # ========================
 
+# Shader translator needs to be revised
+crbug.com/486945330 conformance/glsl/misc/shader-with-double-underscore.html [ Failure ]
+
+# Verification of zero-sized SVGs needs to be changed
+crbug.com/487208470 conformance/textures/misc/tex-image-svg-image-no-natural-width-and-height.html [ Failure ]
+
+# getUniformLocation validation was made more stringent
+crbug.com/487128732 conformance/uniforms/gl-get-uniform-location-errors.html [ Failure ]
+
+# Failing new ASTC offset tests on multiple Android devices
+crbug.com/487128735 [ android android-pixel-2 passthrough ] conformance/extensions/webgl-compressed-texture-astc.html [ Failure ]
+crbug.com/487128735 [ android android-pixel-4 passthrough ] conformance/extensions/webgl-compressed-texture-astc.html [ Failure ]
+
 # Failing new updated tests
 crbug.com/406187744 conformance/offscreencanvas/offscreencanvas-transfer-image-bitmap.html [ Failure ]
 
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_revision.txt b/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
index 178cdf2..ff89f6a 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
+++ b/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
@@ -1,3 +1,3 @@
 # AUTOGENERATED FILE - DO NOT EDIT
 # SEE roll_webgl_conformance.py
-Current webgl revision c01b768bce4a143e152c1870b6ba99ea6267d2b0
+Current webgl revision 8fc2a0dff53abfc0cf2c140d8420759b2036cc54
diff --git a/docs/chrome_browser_design_principles.md b/docs/chrome_browser_design_principles.md
index 841566b..3ce34aac 100644
--- a/docs/chrome_browser_design_principles.md
+++ b/docs/chrome_browser_design_principles.md
@@ -54,7 +54,7 @@
 Public](https://docs.google.com/document/d/1aQRPDX9RjWHE48rAHntsV64VU1-4uZO_nkL6A7ohr2k/).
 
 To keep the dependency graph as precise as possible, we use a pattern called
-[UnownedUserData](ui/base/unowned_user_data/README.md). This allows consumers of
+[UnownedUserData](../ui/base/unowned_user_data/README.md). This allows consumers of
 `BrowserWindowInterface` and `TabInterface` to depend on a specific
 `BrowserWindowFeature` or `TabFeature` without depending on features. This also
 allows for easier unit and integration testing.
diff --git a/docs/webui/webui_build_configuration.md b/docs/webui/webui_build_configuration.md
index 5db503d..12c1a641 100644
--- a/docs/webui/webui_build_configuration.md
+++ b/docs/webui/webui_build_configuration.md
@@ -832,10 +832,11 @@
 
 List of files params:
 files: Required parameter. List of all test related files.
-cc_files: Optional parameter. List of all C++ test files that invoke the Mocha
-          tests. When populated an additional ":check_tests_referenced" target
-          is defined which checks that each Mocha test file is referenced in at
-          least one C++ test file to guard against orphan Mocha tests.
+cc_test_files: Required parameter. List of all C++ test files that invoke the
+               Mocha tests. When populated an additional
+               ":check_tests_referenced" target is defined which checks that
+               each Mocha test file is referenced in at least one C++ test file
+               to guard against orphan Mocha tests.
 
 TypeScript (ts_library()) related params:
 ts_tsconfig_base: See |tsconfig_base| in ts_library(). Optional parameter. If
diff --git a/extensions/browser/api/web_request/extension_web_request_event_router.cc b/extensions/browser/api/web_request/extension_web_request_event_router.cc
index a9aba55..df8bf1629 100644
--- a/extensions/browser/api/web_request/extension_web_request_event_router.cc
+++ b/extensions/browser/api/web_request/extension_web_request_event_router.cc
@@ -108,6 +108,8 @@
 constexpr char kRequestFilterWindowIdKey[] = "windowId";
 constexpr char kRequestFilterOptionsKey[] = "_options";
 
+// TODO(crbug.com/474558883): remove once migration to EventRouter mechanism is
+// complete.
 const char kListenerSubEventNameKey[] = "sub_event_name";
 const char kListenerFilterKey[] = "filter";
 const char kListenerExtraInfoSpecKey[] = "extra_info_spec";
@@ -522,6 +524,8 @@
 
 }  // namespace
 
+// TODO(crbug.com/474558883): remove once migration to EventRouter mechanism is
+// complete.
 const char WebRequestEventRouter::kFilteredLazyListeners[] =
     "web_request.filtered_lazy_listeners";
 
@@ -1899,7 +1903,8 @@
     int render_process_id,
     int web_view_instance_id,
     int worker_thread_id,
-    int64_t service_worker_version_id) {
+    int64_t service_worker_version_id,
+    bool is_lazy) {
   if (!IsWebRequestEvent(event_name)) {
     return false;
   }
@@ -1908,38 +1913,39 @@
     return false;
   }
 
+  BrowserContextID browser_context_id = GetBrowserContextID(browser_context);
   EventListener::ID id(browser_context, extension_id, sub_event_name,
                        render_process_id, web_view_instance_id,
                        worker_thread_id, service_worker_version_id);
-  if (FindEventListener(id) != nullptr) {
+  if (is_lazy &&
+      FindEventListenerBySubEventName(browser_context_id, extension_id,
+                                      event_name, sub_event_name)) {
+    // If listener is already active, we shouldn't add it to the inactive list.
+    // NOTE: we return true since this was a no-op and not a failure.
+    return true;
+  }
+  if (!is_lazy && FindEventListener(id)) {
     // This is likely an abuse of the API by a malicious extension.
     return false;
   }
 
-  LOG(ERROR) << "AddEventListener: " << browser_context
-             << " extension_id: " << extension_id
-             << " extension_name: " << extension_name
-             << " event_name: " << event_name
-             << " sub_event_name: " << sub_event_name
-             << " render_process_id: " << render_process_id
-             << " web_view_instance_id: " << web_view_instance_id
-             << " worker_thread_id: " << worker_thread_id
-             << " service_worker_version_id: " << service_worker_version_id;
-
   auto listener = std::make_unique<EventListener>(std::move(id));
   listener->extension_name = extension_name;
   listener->histogram_value = GetEventHistogramValue(event_name);
   listener->filter = std::move(filter);
   listener->extra_info_spec = extra_info_spec;
+
+  if (is_lazy) {
+    AddLazyListener(browser_context, event_name, std::move(listener));
+    return true;
+  }
+
   if (web_view_instance_id) {
     base::RecordAction(
         base::UserMetricsAction("WebView.WebRequest.AddListener"));
   }
-
   RecordAddEventListenerUMAs(extra_info_spec);
 
-  BrowserContextID browser_context_id = GetBrowserContextID(browser_context);
-
   // This might be a reactivated listener - a listener being added for a
   // lazy context where it was shut down and then respawned. This can only
   // happen for service worker listeners.
@@ -1985,6 +1991,23 @@
   return true;
 }
 
+void WebRequestEventRouter::AddLazyListener(
+    content::BrowserContext* browser_context,
+    const std::string& event_name,
+    std::unique_ptr<EventListener> listener) {
+  BrowserContextID browser_context_id = GetBrowserContextID(browser_context);
+
+  if (listener->HasExtraHeaders()) {
+    IncrementExtraHeadersListenerCount(browser_context);
+  }
+  if (listener->HasSecurityInfo()) {
+    IncrementSecurityInfoListenerCount(browser_context);
+  }
+
+  data_[browser_context_id].inactive_listeners[event_name].push_back(
+      std::move(listener));
+}
+
 WebRequestEventRouter::EventListener* WebRequestEventRouter::FindEventListener(
     const EventListener::ID& id) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -1995,6 +2018,23 @@
 }
 
 WebRequestEventRouter::EventListener*
+WebRequestEventRouter::FindEventListenerBySubEventName(
+    BrowserContextID browser_context_id,
+    const ExtensionId& extension_id,
+    const std::string& event_name,
+    const std::string& sub_event_name) {
+  const Listeners& listeners =
+      data_[browser_context_id].active_listeners[event_name];
+  auto it =
+      std::find_if(listeners.begin(), listeners.end(),
+                   [&extension_id, &sub_event_name](const auto& listener) {
+                     return listener->id.extension_id == extension_id &&
+                            listener->id.sub_event_name == sub_event_name;
+                   });
+  return it != listeners.end() ? it->get() : nullptr;
+}
+
+WebRequestEventRouter::EventListener*
 WebRequestEventRouter::FindEventListenerInContainer(
     const EventListener::ID& id,
     const Listeners& listeners) {
@@ -2176,6 +2216,11 @@
     const ExtensionId& extension_id,
     const EventListener& listener) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (base::FeatureList::IsEnabled(
+          extensions_features::
+              kWebRequestPersistFilteredEventsViaEventRouter)) {
+    return;
+  }
   // Do not persist listeners from incognito contexts.
   // TODO(crbug.com/448893426): support OTR contexts.
   if (browser_context->IsOffTheRecord()) {
@@ -2215,6 +2260,11 @@
     const ExtensionId& extension_id,
     const std::string& sub_event_name) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (base::FeatureList::IsEnabled(
+          extensions_features::
+              kWebRequestPersistFilteredEventsViaEventRouter)) {
+    return;
+  }
   if (browser_context->IsOffTheRecord()) {
     return;
   }
@@ -2429,6 +2479,14 @@
   DCHECK(!browser_context->IsOffTheRecord());
 
   ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context);
+  if (base::FeatureList::IsEnabled(
+          extensions_features::
+              kWebRequestPersistFilteredEventsViaEventRouter)) {
+    // TODO(crbug.com/474558883): If the feature is enabled, the old preferences
+    // are redundant and we should clean them up. Do this once we verify that
+    // the newer feature works correctly.
+    return;
+  }
   const base::ListValue* persisted_listeners =
       prefs->ReadPrefAsList(extension_id, kFilteredLazyListeners);
   if (!persisted_listeners) {
@@ -2492,15 +2550,9 @@
 
   // If we are here, all listeners were loaded successfully. Register them.
   for (auto& [sub_event_name, listener] : loaded_listeners) {
-    if (listener->HasExtraHeaders()) {
-      IncrementExtraHeadersListenerCount(browser_context);
-    }
-    if (listener->HasSecurityInfo()) {
-      IncrementSecurityInfoListenerCount(browser_context);
-    }
     std::string event_name =
         EventRouter::GetBaseEventName(listener->id.sub_event_name);
-    data.inactive_listeners[event_name].push_back(std::move(listener));
+    AddLazyListener(browser_context, event_name, std::move(listener));
   }
 }
 
@@ -2520,6 +2572,33 @@
       .size();
 }
 
+bool WebRequestEventRouter::GetInactiveListenerDetailsForTesting(
+    content::BrowserContext* browser_context,
+    const ExtensionId& extension_id,
+    const std::string& event_name,
+    RequestFilter** filter,
+    int* extra_info_spec) {
+  const ListenerMap& inactive_listeners =
+      data_[GetBrowserContextID(browser_context)].inactive_listeners;
+  auto event_it = inactive_listeners.find(event_name);
+  if (event_it == inactive_listeners.end()) {
+    return false;
+  }
+
+  for (const auto& listener : event_it->second) {
+    if (listener->id.extension_id == extension_id) {
+      if (extra_info_spec) {
+        *extra_info_spec = listener->extra_info_spec;
+      }
+      if (filter) {
+        *filter = &listener->filter;
+      }
+      return true;
+    }
+  }
+  return false;
+}
+
 bool WebRequestEventRouter::HasAnyExtraHeadersListenerImpl(
     content::BrowserContext* browser_context) {
   auto iter = data_.find(GetBrowserContextID(browser_context));
diff --git a/extensions/browser/api/web_request/extension_web_request_event_router.h b/extensions/browser/api/web_request/extension_web_request_event_router.h
index c209f9ef..57ed3cf 100644
--- a/extensions/browser/api/web_request/extension_web_request_event_router.h
+++ b/extensions/browser/api/web_request/extension_web_request_event_router.h
@@ -75,6 +75,8 @@
 
   // Key to the extension preference that stores serialized lazy webRequest
   // listeners.
+  // TODO(crbug.com/474558883): remove once migration to EventRouter mechanism
+  // is complete.
   static const char kFilteredLazyListeners[];
 
   explicit WebRequestEventRouter(content::BrowserContext* browser_context);
@@ -295,7 +297,8 @@
                         int render_process_id,
                         int web_view_instance_id,
                         int worker_thread_id,
-                        int64_t service_worker_version_id);
+                        int64_t service_worker_version_id,
+                        bool is_lazy);
 
   // Removes the listeners for a given <webview>.
   void RemoveWebViewEventListeners(content::BrowserContext* browser_context,
@@ -344,6 +347,8 @@
   // browser context. Called when the extension is loaded.
   // NOTE: loads all listeners or none at all. If the persisted listeners
   // were invalid, it clears the corresponding pref.
+  // TODO(crbug.com/474558883): remove once migration to EventRouter mechanism
+  // is complete.
   void LoadPersistedLazyListeners(content::BrowserContext* browser_context,
                                   const ExtensionId& extension_id);
 
@@ -354,6 +359,14 @@
       content::BrowserContext* browser_context,
       const std::string& event_name);
 
+  // Get details of an inactive listener given event name - for testing only.
+  bool GetInactiveListenerDetailsForTesting(
+      content::BrowserContext* browser_context,
+      const ExtensionId& extension_id,
+      const std::string& event_name,
+      RequestFilter** filter,
+      int* extra_info_spec);
+
   bool HasAnyExtraHeadersListenerForTesting(
       content::BrowserContext* browser_context) {
     return HasAnyExtraHeadersListenerImpl(browser_context);
@@ -423,6 +436,8 @@
 
     // Deserializes a listener from a persisted dictionary value into its
     // inactive (lazy) state. Returns nullptr on failure and sets `error`.
+    // TODO(crbug.com/474558883): remove once migration to EventRouter mechanism
+    // is complete.
     static std::unique_ptr<EventListener> InitFromInactiveListenerValue(
         const base::DictValue& value,
         const ExtensionId& extension_id,
@@ -430,6 +445,8 @@
         std::string* error);
 
     // Serializes a listener for persistence.
+    // TODO(crbug.com/474558883): remove once migration to EventRouter mechanism
+    // is complete.
     base::DictValue ToInactiveListenerValue() const;
 
     bool HasExtraHeaders() const {
@@ -536,6 +553,15 @@
   // Returns the EventListener with the given `id`, or nullptr.
   EventListener* FindEventListener(const EventListener::ID& id);
 
+  // Returns the active EventListener corresponding to the provided
+  // `browser_context_id`, `extension_id`, `event_name`, and `sub_event_name`,
+  // or nullptr if not found.
+  EventListener* FindEventListenerBySubEventName(
+      BrowserContextID browser_context_id,
+      const ExtensionId& extension_id,
+      const std::string& event_name,
+      const std::string& sub_event_name);
+
   // Returns the EventListener with the given `id` from `listeners`.
   EventListener* FindEventListenerInContainer(const EventListener::ID& id,
                                               const Listeners& listeners);
@@ -550,6 +576,13 @@
                             int worker_thread_id,
                             int64_t service_worker_version_id);
 
+  // Adds a listener to the inactive (lazy) listeners list for the specified
+  // context and event. Updates global listener counts (like extra headers and
+  // security info) if applicable.
+  void AddLazyListener(content::BrowserContext* browser_context,
+                       const std::string& event_name,
+                       std::unique_ptr<EventListener> listener);
+
   // Removes a lazy listener registration. This affects both the provided
   // `original_context` and any incognito context associated with it.
   void RemoveLazyListener(content::BrowserContext* original_context,
@@ -557,12 +590,16 @@
                           const std::string& sub_event_name);
 
   // Adds a listener to the persisted lazy listeners for the given extension.
+  // TODO(crbug.com/474558883): remove once migration to EventRouter mechanism
+  // is complete.
   void AddPersistedLazyListener(content::BrowserContext* browser_context,
                                 const ExtensionId& extension_id,
                                 const EventListener& listener);
 
   // Removes a listener from the persisted lazy listeners for the given
   // extension.
+  // TODO(crbug.com/474558883): remove once migration to EventRouter mechanism
+  // is complete.
   void RemovePersistedLazyListener(content::BrowserContext* browser_context,
                                    const ExtensionId& extension_id,
                                    const std::string& sub_event_name);
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc
index 3c67b743..eb2177d 100644
--- a/extensions/browser/api/web_request/web_request_api.cc
+++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -415,10 +415,8 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (!base::FeatureList::IsEnabled(
-          extensions_features::kWebRequestAlternativeAddListener)) {
-    return;
-  }
-  if (details.is_lazy) {
+          extensions_features::
+              kWebRequestPersistFilteredEventsViaEventRouter)) {
     return;
   }
 
@@ -553,14 +551,17 @@
                details.browser_context, details.extension_id, extension_name,
                event_name, sub_event_name, std::move(filter), extra_info_spec,
                details.render_process_id, web_view_instance_id,
-               details.worker_thread_id, details.service_worker_version_id)) {
+               details.worker_thread_id, details.service_worker_version_id,
+               details.is_lazy)) {
     AddMessageToConsoleForListener(details,
                                    blink::mojom::ConsoleMessageLevel::kError,
                                    "Failed to add listener.");
     return;
   }
 
-  helpers::ClearCacheOnNavigation();
+  if (!details.is_lazy) {
+    helpers::ClearCacheOnNavigation();
+  }
 }
 
 void WebRequestAPI::OnListenerRemoved(const EventListenerInfo& details) {
@@ -1201,11 +1202,11 @@
 
   bool success =
       WebRequestEventRouter::Get(browser_context())
-          ->AddEventListener(browser_context(), extension_id_safe(),
-                             extension_name, event_name, sub_event_name,
-                             std::move(filter), extra_info_spec,
-                             render_process_id, web_view_instance_id,
-                             worker_thread_id(), service_worker_version_id());
+          ->AddEventListener(
+              browser_context(), extension_id_safe(), extension_name,
+              event_name, sub_event_name, std::move(filter), extra_info_spec,
+              render_process_id, web_view_instance_id, worker_thread_id(),
+              service_worker_version_id(), /*is_lazy=*/false);
   EXTENSION_FUNCTION_VALIDATE(success);
 
   helpers::ClearCacheOnNavigation();
diff --git a/extensions/browser/url_loader_factory_manager.cc b/extensions/browser/url_loader_factory_manager.cc
index a868295..5aa35a48 100644
--- a/extensions/browser/url_loader_factory_manager.cc
+++ b/extensions/browser/url_loader_factory_manager.cc
@@ -17,7 +17,6 @@
 #include "extensions/common/constants.h"
 #include "extensions/common/cors_util.h"
 #include "extensions/common/extension.h"
-#include "extensions/common/extension_features.h"
 #include "extensions/common/extension_set.h"
 #include "extensions/common/manifest_handlers/permissions_parser.h"
 #include "extensions/common/mojom/host_id.mojom.h"
@@ -123,9 +122,7 @@
                            bool is_for_service_worker,
                            FactoryUser factory_user,
                            network::mojom::URLLoaderFactoryParams* params) {
-  if (is_for_service_worker &&
-      base::FeatureList::IsEnabled(
-          extensions_features::kSkipResetServiceWorkerURLLoaderFactories)) {
+  if (is_for_service_worker) {
     CHECK_EQ(factory_user, FactoryUser::kExtensionProcess);
     params->ignore_factory_reset = true;
   }
diff --git a/extensions/common/api/automation.idl b/extensions/common/api/automation.idl
index 90331fcf..e061bf1 100644
--- a/extensions/common/api/automation.idl
+++ b/extensions/common/api/automation.idl
@@ -54,9 +54,11 @@
     focusChanged,
     focusContext,
     grabbedChanged,
+    grammarMarkerChanged,
     haspopupChanged,
     hide,
     hierarchicalLevelChanged,
+    highlightMarkerChanged,
     hitTestResult,
     hover,
     ignoredChanged,
@@ -121,6 +123,7 @@
     setSizeChanged,
     show,
     sortChanged,
+    spellingMarkerChanged,
     stateChanged,
     subtreeCreated,
     textAttributeChanged,
diff --git a/extensions/common/extension_features.cc b/extensions/common/extension_features.cc
index 28fbac37..986efc1 100644
--- a/extensions/common/extension_features.cc
+++ b/extensions/common/extension_features.cc
@@ -54,9 +54,6 @@
              "EMF_NO_EXTENSION_ID_FOR_EXTENSION_SOURCE",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
-BASE_FEATURE(kSkipResetServiceWorkerURLLoaderFactories,
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 BASE_FEATURE(kEnableWebHidInWebView, base::FEATURE_ENABLED_BY_DEFAULT);
 
 #if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS)
@@ -211,7 +208,7 @@
 BASE_FEATURE(kSearchEngineUnconditionalDialog,
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-BASE_FEATURE(kWebRequestAlternativeAddListener,
-             base::FEATURE_ENABLED_BY_DEFAULT);
+BASE_FEATURE(kWebRequestPersistFilteredEventsViaEventRouter,
+             base::FEATURE_DISABLED_BY_DEFAULT);
 
 }  // namespace extensions_features
diff --git a/extensions/common/extension_features.h b/extensions/common/extension_features.h
index c904fcf..a9fc4de 100644
--- a/extensions/common/extension_features.h
+++ b/extensions/common/extension_features.h
@@ -93,12 +93,6 @@
 // extension).
 BASE_DECLARE_FEATURE(kCheckingNoExtensionIdInExtensionIpcs);
 
-// If enabled, `ResetURLLoaderFactories()` will not reset extensions'
-// service workers URLLoaderFactories used for fetching scripts and
-// sub-resources. This avoids disrupting the worker(s) registration(s)
-// when they are in flight.
-BASE_DECLARE_FEATURE(kSkipResetServiceWorkerURLLoaderFactories);
-
 // If enabled, <webview>s will be allowed to request permission from an
 // embedding Chrome App to request access to Human Interface Devices.
 BASE_DECLARE_FEATURE(kEnableWebHidInWebView);
@@ -322,10 +316,11 @@
 // Allowing them to retrieve certificate information from web requests.
 BASE_DECLARE_FEATURE(kWebRequestSecurityInfo);
 
-// When enabled, use an alternative way to add listeners for the webRequest API,
-// which uses the standard `addListener` only, rather than using
-// WebRequestInternal's custom API.
-BASE_DECLARE_FEATURE(kWebRequestAlternativeAddListener);
+// When enabled, filtered webRequest event listeners for service worker-based
+// extensions are persisted to ExtensionPrefs by the general mechanism in
+// EventRouter. If disabled, they're instead persisted by the custom mechanism
+// in WebRequestEventRouter.
+BASE_DECLARE_FEATURE(kWebRequestPersistFilteredEventsViaEventRouter);
 
 }  // namespace extensions_features
 
diff --git a/extensions/renderer/api/web_request_natives.cc b/extensions/renderer/api/web_request_natives.cc
index 7a63bf83..4f7f940 100644
--- a/extensions/renderer/api/web_request_natives.cc
+++ b/extensions/renderer/api/web_request_natives.cc
@@ -45,7 +45,7 @@
   CHECK_EQ(0, args.Length());
 
   args.GetReturnValue().Set(base::FeatureList::IsEnabled(
-      extensions_features::kWebRequestAlternativeAddListener));
+      extensions_features::kWebRequestPersistFilteredEventsViaEventRouter));
 }
 
 }  // namespace extensions
diff --git a/extensions/renderer/bindings/event_emitter.cc b/extensions/renderer/bindings/event_emitter.cc
index 01de9a8..5517039 100644
--- a/extensions/renderer/bindings/event_emitter.cc
+++ b/extensions/renderer/bindings/event_emitter.cc
@@ -166,7 +166,8 @@
 
   v8::Local<v8::Object> options;
   if (base::FeatureList::IsEnabled(
-          extensions_features::kWebRequestAlternativeAddListener) &&
+          extensions_features::
+              kWebRequestPersistFilteredEventsViaEventRouter) &&
       !arguments->PeekNext().IsEmpty()) {
     // The `options` argument is currently limited to webRequest API only.
     std::string_view event_name = listeners_->GetEventName();
diff --git a/extensions/renderer/bindings/event_emitter_unittest.cc b/extensions/renderer/bindings/event_emitter_unittest.cc
index f0604d1..c03e61b 100644
--- a/extensions/renderer/bindings/event_emitter_unittest.cc
+++ b/extensions/renderer/bindings/event_emitter_unittest.cc
@@ -211,7 +211,7 @@
  public:
   EventEmitterWithAlternativeAddListenerUnittest() {
     feature_list_.InitAndEnableFeature(
-        extensions_features::kWebRequestAlternativeAddListener);
+        extensions_features::kWebRequestPersistFilteredEventsViaEventRouter);
   }
 
  private:
diff --git a/gpu/command_buffer/service/shared_image/compound_image_backing.cc b/gpu/command_buffer/service/shared_image/compound_image_backing.cc
index 07d894f..ae3f003 100644
--- a/gpu/command_buffer/service/shared_image/compound_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/compound_image_backing.cc
@@ -1512,7 +1512,26 @@
     if (!backing)
       continue;
 
-    auto element_client_guid = GetSubBackingGUIDForTracing(mailbox(), i + 1);
+    // When CompoundImageBacking wraps a single backing, use the client's global
+    // Mailbox GUID instead of sub-backing GUID. This ensures correct effective
+    // size attribution to the client process where client claims all of the
+    // memory/effective_size(since client usually has higher
+    // TracingImportance(2) than service side (0)).
+    // This does not work well when CompoundImageBacking has multiple gpu
+    // backings. In that case, each child element creates its own sub-backing
+    // GUID and links to it rather than linking to global mailbox GUID. However,
+    // the client only knows about the single Global Mailbox GUID. As a result,
+    // the client claims the Global GUID, but the GPU service claims the memory
+    // for the individual Sub-Backing GUIDs. This leads to over-reporting
+    // (actual effective_size = Client Size + Sum of Sub-Backings instead of
+    // expected effective_size = Sum of Sub-Backings). This is currently a known
+    // architectural limitation that requires further design to unify memory
+    // attribution (e.g., via dynamic IPC updates to the client about total
+    // elements OR by shifting total ownership to the service with higher
+    // importance).
+    auto element_client_guid =
+        elements_.size() == 1 ? client_guid
+                              : GetSubBackingGUIDForTracing(mailbox(), i + 1);
     std::string element_dump_name =
         base::StringPrintf("%s/element_%d", dump_name.c_str(), i);
     backing->OnMemoryDump(element_dump_name, element_client_guid, pmd,
diff --git a/ios/chrome/app/resources/Settings.bundle/Experimental.plist b/ios/chrome/app/resources/Settings.bundle/Experimental.plist
index e4be106..38895d7b 100644
--- a/ios/chrome/app/resources/Settings.bundle/Experimental.plist
+++ b/ios/chrome/app/resources/Settings.bundle/Experimental.plist
@@ -954,16 +954,6 @@
 			<key>AutocorrectionType</key>
 			<string>No</string>
 		</dict>
-		<dict>
-			<key>Type</key>
-			<string>PSToggleSwitchSpecifier</string>
-			<key>Title</key>
-			<string>Lens Unified Flags Menu</string>
-			<key>Key</key>
-			<string>LensUnifiedFlagsMenu</string>
-			<key>DefaultValue</key>
-			<false/>
-		</dict>
 	</array>
 </dict>
 </plist>
diff --git a/ios/chrome/browser/ai_prototyping/coordinator/ai_prototyping_mediator.mm b/ios/chrome/browser/ai_prototyping/coordinator/ai_prototyping_mediator.mm
index bf249bf..992fa448 100644
--- a/ios/chrome/browser/ai_prototyping/coordinator/ai_prototyping_mediator.mm
+++ b/ios/chrome/browser/ai_prototyping/coordinator/ai_prototyping_mediator.mm
@@ -582,9 +582,8 @@
               updateQueryResult:@"Action executed successfully."
                      forFeature:AIPrototypingFeature::kActuationTools];
         } else {
-          NSString* errorMsg =
-              [NSString stringWithFormat:@"Action failed: %s",
-                                         result.error().message.c_str()];
+          NSString* errorMsg = base::SysUTF8ToNSString(base::StringPrintf(
+              "Action failed: %s", GetActuationErrorMessage(result.error())));
           NSLog(@"[AIPrototypingMediator] %@", errorMsg);
           [weakSelf.consumer
               updateQueryResult:errorMsg
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.h b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.h
index 45281db..e6b47d4 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.h
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.h
@@ -15,6 +15,14 @@
 #import "ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mutator.h"
 #import "ios/chrome/browser/shared/public/commands/autofill_commands.h"
 
+// Represents the different types of save card actions that the bottom sheet can
+// handle.
+enum class SaveCardActionType {
+  kLocal,
+  kUpload,
+  kSaveScanAndFill,
+};
+
 // This mediator tracks SaveCardBottomSheetModel to update the view. It also
 // receives user actions to be communicated to the model.
 @interface SaveCardBottomSheetMediator
@@ -41,6 +49,11 @@
 // Returns whether bottomsheet is already in the process of dismissing.
 - (BOOL)isDismissingForTesting;
 
+// Returns the specific type of save card action for this bottom sheet.
+// This is used by the coordinator to determine which view controller flow to
+// present.
+- (SaveCardActionType)actionType;
+
 #pragma mark - SaveCardBottomSheetModel Observer methods
 
 - (void)onCreditCardUploadCompleted:(BOOL)cardSaved;
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.mm b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.mm
index e4d2b14..1d89c3e 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator.mm
@@ -213,6 +213,16 @@
       SaveCreditCardPromptOverlayType::kBottomSheet);
 }
 
+- (SaveCardActionType)actionType {
+  if (_saveCardBottomSheetModel->save_card_delegate()->is_for_upload()) {
+    return SaveCardActionType::kUpload;
+  }
+  if (_saveCardBottomSheetModel->save_card_delegate()->is_for_local_save()) {
+    return SaveCardActionType::kLocal;
+  }
+  return SaveCardActionType::kSaveScanAndFill;
+}
+
 #pragma mark - SaveCardBottomSheetDataSource
 
 - (AboveTitleImageLogoType)logoType {
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator_unittest.mm b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator_unittest.mm
index 339be54..e67762a1 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator_unittest.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_mediator_unittest.mm
@@ -745,6 +745,35 @@
       LegacySaveCardPromptResult::kClosed, 1);
 }
 
+// Test that actionType returns kSaveScanAndFill when initialized for scan and
+// fill.
+TEST_F(SaveCardBottomSheetMediatorTest, ActionTypeForScanAndFill) {
+  using Variant = std::variant<
+      autofill::payments::PaymentsAutofillClient::LocalSaveCardPromptCallback,
+      autofill::payments::PaymentsAutofillClient::UploadSaveCardPromptCallback,
+      autofill::payments::PaymentsAutofillClient::
+          CardSaveAndFillDialogCallback>;
+
+  std::unique_ptr<autofill::SaveCardBottomSheetModel> model =
+      std::make_unique<MockSaveCardBottomSheetModel>(
+          CreateAutofillSaveCardUiInfo(/*for_upload=*/false),
+          Variant(static_cast<autofill::payments::PaymentsAutofillClient::
+                                  CardSaveAndFillDialogCallback>(
+              base::DoNothing())),
+          autofill::payments::PaymentsAutofillClient::SaveCreditCardOptions()
+              .with_num_strikes(0));
+
+  SaveCardBottomSheetMediator* scan_and_fill_mediator =
+      [[SaveCardBottomSheetMediator alloc]
+                  initWithUIModel:std::move(model)
+          autofillCommandsHandler:mock_autofill_commands_handler_];
+
+  EXPECT_EQ([scan_and_fill_mediator actionType],
+            SaveCardActionType::kSaveScanAndFill);
+
+  [scan_and_fill_mediator disconnect];
+}
+
 class SaveCardBottomSheetMediatorMetricsTestWithCardSaveType
     : public SaveCardBottomSheetMediatorTest,
       public testing::WithParamInterface<
diff --git a/ios/chrome/browser/content_suggestions/test/content_suggestions_egtest.mm b/ios/chrome/browser/content_suggestions/test/content_suggestions_egtest.mm
index 3fb33b0..e603551 100644
--- a/ios/chrome/browser/content_suggestions/test/content_suggestions_egtest.mm
+++ b/ios/chrome/browser/content_suggestions/test/content_suggestions_egtest.mm
@@ -593,7 +593,7 @@
   // Check the form is displayed with the correct title and footer.
   [[EarlGrey
       selectElementWithMatcher:
-          chrome_test_util::HeaderWithAccessibilityLabelId(
+          chrome_test_util::NavigationBarTitleWithAccessibilityLabelId(
               IDS_IOS_CONTENT_SUGGESTIONS_PIN_SITE_EDIT_PINNED_SITE_TITLE)]
       assertWithMatcher:grey_sufficientlyVisible()];
   // Check the "Name" field and type a new value.
@@ -700,13 +700,7 @@
 
 // Tests pinning 8 sites and verifying the "Add site" button disappears after 8
 // sites are added, and reappears after unpinning one.
-// TODO(crbug.com/483977973): Reenable this test on device.
-#if TARGET_OS_SIMULATOR
-#define MAYBE_testMostVisitedPinEightSites testMostVisitedPinEightSites
-#else
-#define MAYBE_testMostVisitedPinEightSites DISABLED_testMostVisitedPinEightSites
-#endif
-- (void)MAYBE_testMostVisitedPinEightSites {
+- (void)testMostVisitedPinEightSites {
   id<GREYMatcher> addSiteButton = grey_accessibilityID(
       AccessibilityIdentifierForMostVisitedCellAtIndex(-1));
   // Add 8 pinned sites. Before pinning each, verify that the "Add site" button
@@ -738,7 +732,7 @@
   // Now the "+" button should be back.
   ScrollMostVisitedToRightEdge();
   [[EarlGrey selectElementWithMatcher:addSiteButton]
-      assertWithMatcher:grey_sufficientlyVisible()];
+      assertWithMatcher:grey_interactable()];
 }
 
 #pragma mark - Test utils
@@ -793,7 +787,7 @@
   // Verify form title.
   [[EarlGrey
       selectElementWithMatcher:
-          chrome_test_util::HeaderWithAccessibilityLabelId(
+          chrome_test_util::NavigationBarTitleWithAccessibilityLabelId(
               IDS_IOS_CONTENT_SUGGESTIONS_PIN_SITE_ADD_PINNED_SITE_TITLE)]
       assertWithMatcher:grey_sufficientlyVisible()];
   id<GREYMatcher> saveButton = grey_allOf(
diff --git a/ios/chrome/browser/intelligence/actuation/OWNERS b/ios/chrome/browser/intelligence/actuation/OWNERS
new file mode 100644
index 0000000..65f2ffe4
--- /dev/null
+++ b/ios/chrome/browser/intelligence/actuation/OWNERS
@@ -0,0 +1 @@
+kaklilu@chromium.org
\ No newline at end of file
diff --git a/ios/chrome/browser/intelligence/actuation/model/BUILD.gn b/ios/chrome/browser/intelligence/actuation/model/BUILD.gn
index b84628d0..e61411a 100644
--- a/ios/chrome/browser/intelligence/actuation/model/BUILD.gn
+++ b/ios/chrome/browser/intelligence/actuation/model/BUILD.gn
@@ -2,6 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+source_set("actuation_error") {
+  sources = [
+    "actuation_error.h",
+    "actuation_error.mm",
+  ]
+  deps = [ "//base" ]
+}
+
 source_set("model") {
   sources = [
     "actuation_service.h",
@@ -11,7 +19,10 @@
     "actuation_tool_factory.h",
     "actuation_tool_factory.mm",
   ]
-  public_deps = [ "//ios/chrome/browser/intelligence/actuation/model/tools:actuation_interface" ]
+  public_deps = [
+    ":actuation_error",
+    "//ios/chrome/browser/intelligence/actuation/model/tools:actuation_interface",
+  ]
   deps = [
     "//base",
     "//components/keyed_service/core",
diff --git a/ios/chrome/browser/intelligence/actuation/model/actuation_app_interface.mm b/ios/chrome/browser/intelligence/actuation/model/actuation_app_interface.mm
index 808ae22b..3a03c21 100644
--- a/ios/chrome/browser/intelligence/actuation/model/actuation_app_interface.mm
+++ b/ios/chrome/browser/intelligence/actuation/model/actuation_app_interface.mm
@@ -54,7 +54,8 @@
         if (result.has_value()) {
           completion(nil);
         } else {
-          NSString* errorMsg = base::SysUTF8ToNSString(result.error().message);
+          NSString* errorMsg =
+              base::SysUTF8ToNSString(GetActuationErrorMessage(result.error()));
           completion([NSError
               errorWithDomain:@"ActuationErrorCode"
                          code:(NSInteger)result.error().code
diff --git a/ios/chrome/browser/intelligence/actuation/model/actuation_error.h b/ios/chrome/browser/intelligence/actuation/model/actuation_error.h
index 59ea25e..8624375 100644
--- a/ios/chrome/browser/intelligence/actuation/model/actuation_error.h
+++ b/ios/chrome/browser/intelligence/actuation/model/actuation_error.h
@@ -5,30 +5,87 @@
 #ifndef IOS_CHROME_BROWSER_INTELLIGENCE_ACTUATION_MODEL_ACTUATION_ERROR_H_
 #define IOS_CHROME_BROWSER_INTELLIGENCE_ACTUATION_MODEL_ACTUATION_ERROR_H_
 
+#import <optional>
 #import <string>
 
-// Error codes for ActuationService.
+// Error codes for actuation in Chrome on iOS.
+//
+// This enum follows the structure of `ActionResultCode` from
+// chrome/common/actor.mojom, using numbered ranges to group errors by category.
+//
+// 0-99: General errors that aren't specific to any tool.
+// 100-199: Tool creation errors that aren't specific to any tool.
+// 200-299: JavaScriptFeature errors that aren't specific to any tool.
+// X00-X99 - A tool-specific error; each tool gets a reserved range of values.
 enum class ActuationErrorCode {
+  // General errors (0-99).
+
   // Default error code for unknown or unspecified failures.
-  kUnknown,
+  // A more specific error code should be used when possible.
+  kUnknown = 0,
+  // There is not an ActuationTool that supports the given action.
+  kUnsupportedAction = 1,
   // The specific tool type is disabled via the 'DisabledTools' feature
   // parameter.
-  kToolDisabled,
-  // The action provided in the proto is not recognized or supported.
-  kUnsupportedAction,
-  // The factory failed to create a valid tool object from the tool data.
-  kToolCreationFailed,
-  // The tool encountered an error during execution (e.g., invalid
-  // parameters, missing dependencies).
-  kExecutionFailed,
-  // The tool failed during JavaScript execution.
-  kJavascriptExecutionFailed,
+  kToolDisabledByFeature = 2,
+  // The tool failed to execute because required dependencies were missing.
+  // Tool-specific execution errors should be added in their respective
+  // code ranges.
+  kExecutionMissingDependencies = 3,
+
+  // Tool Creation Errors (100-199).
+
+  // The tool creation failed because the action proto was missing required
+  // fields.
+  kCreationMissingRequiredFields = 100,
+  // The target tab for the action could not be found.
+  kCreationTargetTabNotFound = 101,
+  // Failed to retrieve the WebStateList from the browser.
+  kCreationMissingWebStateList = 102,
+  // Failed to retrieve the WebState from the WebStateList.
+  kCreationMissingWebState = 103,
+
+  // JavaScript Feature Errors (200-299).
+
+  // The JavaScript feature received a result from the JavaScript that didn't
+  // match the format it expected.
+  kJavascriptFeatureGotInvalidResult = 200,
+  // The JavaScriptFeature::CallJavaScriptFunction call failed.
+  kJavascriptFeatureFailedToCallJavaScriptFunction = 201,
+  // The JavaScript function failed during execution.
+  // When this is used, the ActuationError.message should be populated with an
+  // error message from the JavaScript that provides more context.
+  kJavascriptFeatureFailedInJavaScriptExecution = 202,
+
+  // Navigation Tool Errors (300-399).
+
+  // The requested URL for navigation was invalid.
+  kNavigationInvalidURL = 300,
+  // The tab to be navigated is not realized.
+  // See docs/ios/unrealized_web_state.md.
+  kNavigationTabNotRealized = 301,
 };
 
 // Represents an error that occurred during actuation.
 struct ActuationError {
+  ActuationError(ActuationErrorCode code,
+                 std::optional<std::string> message = std::nullopt);
+  ~ActuationError();
+
+  ActuationError(const ActuationError& other);
+  ActuationError& operator=(const ActuationError& other);
+
+  ActuationError(ActuationError&& other);
+  ActuationError& operator=(ActuationError&& other);
+
   ActuationErrorCode code;
-  std::string message;
+  // If not set, a default message for the error code will be used.
+  // This is primarily used for kJavascriptExecutionFailed to provide
+  // detailed JS error info.
+  std::optional<std::string> message = std::nullopt;
 };
 
+// Returns a localized error message for the given error.
+std::string GetActuationErrorMessage(const ActuationError& error);
+
 #endif  // IOS_CHROME_BROWSER_INTELLIGENCE_ACTUATION_MODEL_ACTUATION_ERROR_H_
diff --git a/ios/chrome/browser/intelligence/actuation/model/actuation_error.mm b/ios/chrome/browser/intelligence/actuation/model/actuation_error.mm
new file mode 100644
index 0000000..0e3377c3
--- /dev/null
+++ b/ios/chrome/browser/intelligence/actuation/model/actuation_error.mm
@@ -0,0 +1,56 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/intelligence/actuation/model/actuation_error.h"
+
+#import "base/notreached.h"
+
+ActuationError::ActuationError(ActuationErrorCode code,
+                               std::optional<std::string> message)
+    : code(code), message(std::move(message)) {}
+
+ActuationError::~ActuationError() = default;
+
+ActuationError::ActuationError(const ActuationError& other) = default;
+ActuationError& ActuationError::operator=(const ActuationError& other) =
+    default;
+
+ActuationError::ActuationError(ActuationError&& other) = default;
+ActuationError& ActuationError::operator=(ActuationError&& other) = default;
+
+std::string GetActuationErrorMessage(const ActuationError& error) {
+  if (error.message.has_value()) {
+    return error.message.value();
+  }
+  switch (error.code) {
+    case ActuationErrorCode::kUnknown:
+      return "Unknown error.";
+    case ActuationErrorCode::kUnsupportedAction:
+      return "There isn't a tool to support this action.";
+    case ActuationErrorCode::kToolDisabledByFeature:
+      return "Tool is disabled via feature parameter.";
+    case ActuationErrorCode::kExecutionMissingDependencies:
+      return "On tool execution, required dependencies were missing.";
+    case ActuationErrorCode::kCreationMissingRequiredFields:
+      return "On tool creation, required fields were missing.";
+    case ActuationErrorCode::kCreationTargetTabNotFound:
+      return "On tool creation, target tab isn't in any Browser.";
+    case ActuationErrorCode::kCreationMissingWebStateList:
+      return "On tool creation, failed to get WebStateList.";
+    case ActuationErrorCode::kCreationMissingWebState:
+      return "On tool creation, failed to get WebState.";
+    case ActuationErrorCode::kJavascriptFeatureGotInvalidResult:
+      return "The JavaScriptFeature got an unexpected response from the "
+             "JavaScript function.";
+    case ActuationErrorCode::kJavascriptFeatureFailedToCallJavaScriptFunction:
+      return "The JavaScriptFeature::CallJavaScriptFunction call failed.";
+    case ActuationErrorCode::kJavascriptFeatureFailedInJavaScriptExecution:
+      return "The JavaScriptFeature failed when executing the JavaScript.";
+    case ActuationErrorCode::kNavigationInvalidURL:
+      return "Navigation failed due to invalid destination URL.";
+    case ActuationErrorCode::kNavigationTabNotRealized:
+      return "Navigation failed because the target tab is not realized.";
+  }
+  NOTREACHED();
+}
diff --git a/ios/chrome/browser/intelligence/actuation/model/actuation_service.mm b/ios/chrome/browser/intelligence/actuation/model/actuation_service.mm
index 9bb3184..48cc365 100644
--- a/ios/chrome/browser/intelligence/actuation/model/actuation_service.mm
+++ b/ios/chrome/browser/intelligence/actuation/model/actuation_service.mm
@@ -31,15 +31,13 @@
   if (action.action_case() ==
       optimization_guide::proto::Action::ACTION_NOT_SET) {
     std::move(callback).Run(base::unexpected(
-        ActuationError{ActuationErrorCode::kUnsupportedAction,
-                       "There isn't a tool to support this action."}));
+        ActuationError{ActuationErrorCode::kUnsupportedAction}));
     return;
   }
 
   if (IsToolDisabled(action.action_case())) {
     std::move(callback).Run(base::unexpected(
-        ActuationError{ActuationErrorCode::kToolDisabled,
-                       "Tool is disabled via feature parameter."}));
+        ActuationError{ActuationErrorCode::kToolDisabledByFeature}));
     return;
   }
 
diff --git a/ios/chrome/browser/intelligence/actuation/model/actuation_service_unittest.mm b/ios/chrome/browser/intelligence/actuation/model/actuation_service_unittest.mm
index be68c94..a334d4c 100644
--- a/ios/chrome/browser/intelligence/actuation/model/actuation_service_unittest.mm
+++ b/ios/chrome/browser/intelligence/actuation/model/actuation_service_unittest.mm
@@ -8,7 +8,6 @@
 #import "base/test/task_environment.h"
 #import "base/types/expected.h"
 #import "components/optimization_guide/proto/features/actions_data.pb.h"
-#import "ios/chrome/browser/intelligence/actuation/model/actuation_error.h"
 #import "ios/chrome/browser/intelligence/actuation/model/actuation_service_factory.h"
 #import "ios/chrome/browser/intelligence/actuation/model/tools/actuation_tool.h"
 #import "ios/chrome/browser/intelligence/features/features.h"
diff --git a/ios/chrome/browser/intelligence/actuation/model/actuation_tool_factory.mm b/ios/chrome/browser/intelligence/actuation/model/actuation_tool_factory.mm
index dd73955..183b2a9 100644
--- a/ios/chrome/browser/intelligence/actuation/model/actuation_tool_factory.mm
+++ b/ios/chrome/browser/intelligence/actuation/model/actuation_tool_factory.mm
@@ -24,7 +24,7 @@
     case optimization_guide::proto::Action::kNavigate:
       return NavigateTool::Create(action.navigate(), profile);
     default:
-      return base::unexpected(ActuationError{
-          ActuationErrorCode::kUnsupportedAction, "Unsupported action"});
+      return base::unexpected(
+          ActuationError{ActuationErrorCode::kUnsupportedAction});
   }
 }
diff --git a/ios/chrome/browser/intelligence/actuation/model/tools/BUILD.gn b/ios/chrome/browser/intelligence/actuation/model/tools/BUILD.gn
index 553957c3..bb593d3d 100644
--- a/ios/chrome/browser/intelligence/actuation/model/tools/BUILD.gn
+++ b/ios/chrome/browser/intelligence/actuation/model/tools/BUILD.gn
@@ -2,9 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//ios/web/public/js_messaging/compile_ts.gni")
+import("//ios/web/public/js_messaging/optimize_ts.gni")
+
 source_set("actuation_interface") {
   sources = [ "actuation_tool.h" ]
 
+  public_deps =
+      [ "//ios/chrome/browser/intelligence/actuation/model:actuation_error" ]
   deps = [ "//base" ]
 }
 
@@ -18,6 +23,7 @@
     ":actuation_interface",
     "//base",
     "//components/optimization_guide/proto:optimization_guide_proto",
+    "//ios/chrome/browser/intelligence/actuation/model:actuation_error",
     "//ios/chrome/browser/shared/model/browser",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/shared/model/web_state_list:utils",
@@ -27,21 +33,64 @@
   ]
 }
 
-source_set("unit_tests") {
-  testonly = true
-  sources = [ "navigate_tool_unittest.mm" ]
+compile_ts("actuation_utils_ts") {
+  sources = [ "resources/actuation_utils.ts" ]
+}
+
+optimize_ts("click_tool_ts") {
+  sources = [ "resources/click_tool.ts" ]
+  output_name = "click_tool"
+
+  deps = [
+    "//ios/chrome/browser/intelligence/actuation/model/tools:actuation_utils_ts",
+    "//ios/web/public/js_messaging:gcrweb",
+  ]
+}
+
+source_set("java_script_features") {
+  sources = [
+    "click_tool_java_script_feature.h",
+    "click_tool_java_script_feature.mm",
+  ]
+
   deps = [
     ":actuation_interface",
+    ":click_tool_ts",
+    "//base",
+    "//components/optimization_guide/proto:optimization_guide_proto",
+    "//ios/web/public",
+    "//ios/web/public/js_messaging",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "click_tool_java_script_feature_unittest.mm",
+    "click_tool_js_unittest.mm",
+    "navigate_tool_unittest.mm",
+  ]
+
+  deps = [
+    ":actuation_interface",
+    ":java_script_features",
     ":navigate_tool",
     "//base/test:test_support",
     "//components/optimization_guide/proto:optimization_guide_proto",
+    "//ios/chrome/browser/intelligence/actuation/model:actuation_error",
     "//ios/chrome/browser/shared/model/browser",
     "//ios/chrome/browser/shared/model/browser/test:test_support",
     "//ios/chrome/browser/shared/model/profile/test",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/url_loading/model",
     "//ios/chrome/browser/url_loading/model:test_support",
+    "//ios/web/common:features",
+    "//ios/web/public/js_messaging",
+    "//ios/web/public/test",
+    "//ios/web/public/test:javascript_test",
+    "//ios/web/public/test:util",
     "//ios/web/public/test/fakes",
+    "//net:test_support",
     "//testing/gtest",
   ]
 }
diff --git a/ios/chrome/browser/intelligence/actuation/model/tools/click_tool_java_script_feature.h b/ios/chrome/browser/intelligence/actuation/model/tools/click_tool_java_script_feature.h
new file mode 100644
index 0000000..455b9685
--- /dev/null
+++ b/ios/chrome/browser/intelligence/actuation/model/tools/click_tool_java_script_feature.h
@@ -0,0 +1,49 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_INTELLIGENCE_ACTUATION_MODEL_TOOLS_CLICK_TOOL_JAVA_SCRIPT_FEATURE_H_
+#define IOS_CHROME_BROWSER_INTELLIGENCE_ACTUATION_MODEL_TOOLS_CLICK_TOOL_JAVA_SCRIPT_FEATURE_H_
+
+#import <optional>
+
+#import "base/no_destructor.h"
+#import "ios/chrome/browser/intelligence/actuation/model/tools/actuation_tool.h"
+#import "ios/web/public/js_messaging/java_script_feature.h"
+
+namespace base {
+class Value;
+}
+
+namespace web {
+class WebFrame;
+}  // namespace web
+
+namespace optimization_guide {
+namespace proto {
+class ClickAction;
+}  // namespace proto
+}  // namespace optimization_guide
+
+// A feature that provides methods to execute various actions in the web page.
+class ClickToolJavaScriptFeature : public web::JavaScriptFeature {
+ public:
+  static ClickToolJavaScriptFeature* GetInstance();
+
+  // Executes the click action on the given WebFrame.
+  void Click(web::WebFrame* web_frame,
+             const optimization_guide::proto::ClickAction& action,
+             ActuationTool::ActuationCallback callback);
+
+ protected:
+  ClickToolJavaScriptFeature();
+  ~ClickToolJavaScriptFeature() override;
+
+ private:
+  friend class base::NoDestructor<ClickToolJavaScriptFeature>;
+
+  void ProcessClickResult(ActuationTool::ActuationCallback callback,
+                          const base::Value* click_result);
+};
+
+#endif  // IOS_CHROME_BROWSER_INTELLIGENCE_ACTUATION_MODEL_TOOLS_CLICK_TOOL_JAVA_SCRIPT_FEATURE_H_
diff --git a/ios/chrome/browser/intelligence/actuation/model/tools/click_tool_java_script_feature.mm b/ios/chrome/browser/intelligence/actuation/model/tools/click_tool_java_script_feature.mm
new file mode 100644
index 0000000..a4ef872
--- /dev/null
+++ b/ios/chrome/browser/intelligence/actuation/model/tools/click_tool_java_script_feature.mm
@@ -0,0 +1,90 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/intelligence/actuation/model/tools/click_tool_java_script_feature.h"
+
+#import "base/check.h"
+#import "base/functional/callback_helpers.h"
+#import "base/values.h"
+#import "components/optimization_guide/proto/features/actions_data.pb.h"
+#import "ios/chrome/browser/intelligence/actuation/model/actuation_error.h"
+#import "ios/chrome/browser/intelligence/actuation/model/tools/actuation_tool.h"
+#import "ios/web/public/js_messaging/web_frame.h"
+
+namespace {
+const char kScriptName[] = "click_tool";
+}  // namespace
+
+// static
+ClickToolJavaScriptFeature* ClickToolJavaScriptFeature::GetInstance() {
+  static base::NoDestructor<ClickToolJavaScriptFeature> instance;
+  return instance.get();
+}
+
+// Note: Error strings in this file are for debugging purposes and are not
+// displayed to the user.
+ClickToolJavaScriptFeature::ClickToolJavaScriptFeature()
+    : web::JavaScriptFeature(
+          web::ContentWorld::kIsolatedWorld,
+          {FeatureScript::CreateWithFilename(
+              kScriptName,
+              FeatureScript::InjectionTime::kDocumentStart,
+              // TODO (crbug.com/476090817) - Inject in all frames once we can
+              // reliably identify iframes in JS and native code.
+              FeatureScript::TargetFrames::kMainFrame,
+              FeatureScript::ReinjectionBehavior::kInjectOncePerWindow)}) {}
+
+ClickToolJavaScriptFeature::~ClickToolJavaScriptFeature() = default;
+
+void ClickToolJavaScriptFeature::Click(
+    web::WebFrame* web_frame,
+    const optimization_guide::proto::ClickAction& action,
+    ActuationTool::ActuationCallback callback) {
+  CHECK(web_frame);
+  CHECK(action.has_target() && action.target().has_coordinate());
+  CHECK(action.has_click_count() && action.has_click_type());
+
+  base::ListValue parameters;
+  parameters.Append(action.target().coordinate().x());
+  parameters.Append(action.target().coordinate().y());
+  parameters.Append(static_cast<int>(action.click_type()));
+  parameters.Append(static_cast<int>(action.click_count()));
+  parameters.Append(
+      static_cast<int>(action.target().coordinate().pixel_type()));
+
+  auto [cb_for_js, cb_for_error] = base::SplitOnceCallback(std::move(callback));
+  bool sent = CallJavaScriptFunction(
+      web_frame, "click_tool.clickByCoordinate", parameters,
+      base::BindOnce(&ClickToolJavaScriptFeature::ProcessClickResult,
+                     base::Unretained(GetInstance()), std::move(cb_for_js)),
+      base::Milliseconds(web::kJavaScriptFunctionCallDefaultTimeout));
+
+  if (!sent) {
+    std::move(cb_for_error)
+        .Run(base::unexpected(ActuationError{
+            ActuationErrorCode::
+                kJavascriptFeatureFailedToCallJavaScriptFunction}));
+  }
+}
+
+void ClickToolJavaScriptFeature::ProcessClickResult(
+    ActuationTool::ActuationCallback callback,
+    const base::Value* click_result) {
+  if (!click_result || !click_result->is_dict()) {
+    std::move(callback).Run(base::unexpected(ActuationError{
+        ActuationErrorCode::kJavascriptFeatureGotInvalidResult}));
+    return;
+  }
+  const base::DictValue& result_dict = click_result->GetDict();
+  bool success = result_dict.FindBool("success").value_or(false);
+  const std::string* error_message = result_dict.FindString("message");
+  if (!success) {
+    // TODO: (crbug.com/476090817) - Add support for actuating in iframes here.
+    std::move(callback).Run(base::unexpected(ActuationError{
+        ActuationErrorCode::kJavascriptFeatureFailedInJavaScriptExecution,
+        error_message ? *error_message : "Unknown error in JS."}));
+    return;
+  }
+  std::move(callback).Run(base::ok());
+}
diff --git a/ios/chrome/browser/intelligence/actuation/model/tools/click_tool_java_script_feature_unittest.mm b/ios/chrome/browser/intelligence/actuation/model/tools/click_tool_java_script_feature_unittest.mm
new file mode 100644
index 0000000..81562cbd
--- /dev/null
+++ b/ios/chrome/browser/intelligence/actuation/model/tools/click_tool_java_script_feature_unittest.mm
@@ -0,0 +1,206 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/intelligence/actuation/model/tools/click_tool_java_script_feature.h"
+
+#import "base/test/bind.h"
+#import "base/test/ios/wait_util.h"
+#import "base/test/scoped_feature_list.h"
+#import "base/test/test_future.h"
+#import "components/optimization_guide/proto/features/actions_data.pb.h"
+#import "ios/chrome/browser/intelligence/actuation/model/actuation_error.h"
+#import "ios/chrome/browser/intelligence/actuation/model/tools/actuation_tool.h"
+#import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
+#import "ios/web/common/features.h"
+#import "ios/web/public/js_messaging/web_frames_manager.h"
+#import "ios/web/public/test/fakes/fake_web_client.h"
+#import "ios/web/public/test/fakes/fake_web_state.h"
+#import "ios/web/public/test/js_test_util.h"
+#import "ios/web/public/test/scoped_testing_web_client.h"
+#import "ios/web/public/test/web_state_test_util.h"
+#import "ios/web/public/test/web_task_environment.h"
+#import "ios/web/public/web_state.h"
+#import "testing/gtest/include/gtest/gtest.h"
+#import "testing/platform_test.h"
+
+using optimization_guide::proto::ClickAction;
+
+namespace {
+
+// Constants for the standard HTML page.
+constexpr int kHtmlWidth = 500;
+constexpr int kHtmlHeight = 500;
+constexpr int kMidPointX = kHtmlWidth / 2;
+constexpr int kMidPointY = kHtmlHeight / 2;
+
+// TODO(crbug.com/472289820): Use ChromeTestWithWebState once it's introduced.
+class ClickToolJavaScriptFeatureTest : public PlatformTest {
+ protected:
+  ClickToolJavaScriptFeatureTest()
+      : web_client_(std::make_unique<web::FakeWebClient>()) {
+    // TODO(crbug.com/483433952): Remove this once it's enabled by default.
+    scoped_feature_list_.InitAndEnableFeature(
+        web::features::kAssertOnJavaScriptErrors);
+    profile_ = TestProfileIOS::Builder().Build();
+
+    web::WebState::CreateParams params(profile_.get());
+    web_state_ = web::WebState::Create(params);
+    web_state_->GetView();
+    web_state_->SetKeepRenderProcessAlive(true);
+
+    web::test::OverrideJavaScriptFeatures(profile_.get(), {feature()});
+  }
+
+  void SetUp() override {
+    PlatformTest::SetUp();
+    NSString* html = [NSString
+        stringWithFormat:
+            @"<html><body style='width: %dpx; height: %dpx;'></body></html>",
+            kHtmlWidth, kHtmlHeight];
+    web::test::LoadHtml(html, web_state());
+  }
+
+  web::WebState* web_state() { return web_state_.get(); }
+
+  ClickToolJavaScriptFeature* feature() {
+    return ClickToolJavaScriptFeature::GetInstance();
+  }
+
+  ClickAction CreateClickAction(int x = kMidPointX, int y = kMidPointY) {
+    ClickAction action;
+    action.mutable_target()->mutable_coordinate()->set_x(x);
+    action.mutable_target()->mutable_coordinate()->set_y(y);
+    action.set_click_type(ClickAction::LEFT);
+    action.set_click_count(ClickAction::SINGLE);
+    action.mutable_target()->mutable_coordinate()->set_pixel_type(
+        optimization_guide::proto::Coordinate::PIXEL_TYPE_DIPS);
+    return action;
+  }
+
+  web::WebFrame* WaitForMainFrame() {
+    __block web::WebFrame* main_frame = nullptr;
+    CHECK(base::test::ios::WaitUntilConditionOrTimeout(
+        base::test::ios::kWaitForJSCompletionTimeout, ^bool {
+          web::WebFramesManager* frames_manager =
+              feature()->GetWebFramesManager(web_state());
+          main_frame = frames_manager->GetMainWebFrame();
+          return main_frame != nullptr;
+        }));
+    return main_frame;
+  }
+
+  base::test::ScopedFeatureList scoped_feature_list_;
+  web::ScopedTestingWebClient web_client_;
+  web::WebTaskEnvironment task_environment_;
+  std::unique_ptr<TestProfileIOS> profile_;
+  std::unique_ptr<web::WebState> web_state_;
+};
+
+TEST_F(ClickToolJavaScriptFeatureTest, JsReturnsNonDict) {
+  web::WebFrame* main_frame = WaitForMainFrame();
+
+  // Override the JS function to return a string.
+  web::test::ExecuteJavaScriptForFeature(
+      web_state(),
+      @"__gCrWeb.getRegisteredApi('click_tool').addFunction('clickByCoordinate'"
+      @", "
+      @"  function() { return 'unexpected type'; }"
+      @"); true;",
+      feature());
+
+  ClickAction action = CreateClickAction();
+
+  base::test::TestFuture<ActuationTool::ActuationResult> future;
+  feature()->Click(main_frame, action, future.GetCallback());
+
+  auto result = future.Get();
+  EXPECT_FALSE(result.has_value());
+  EXPECT_EQ(result.error().code,
+            ActuationErrorCode::kJavascriptFeatureGotInvalidResult);
+}
+
+TEST_F(ClickToolJavaScriptFeatureTest, JsReturnsError) {
+  web::WebFrame* main_frame = WaitForMainFrame();
+
+  // Override the JS function to return an error dictionary.
+  web::test::ExecuteJavaScriptForFeature(
+      web_state(),
+      @"__gCrWeb.getRegisteredApi('click_tool').addFunction('clickByCoordinate'"
+      @", "
+      @"  function() { return {success: false, message: 'Custom JS Error'}; }"
+      @"); true;",
+      feature());
+
+  ClickAction action = CreateClickAction();
+
+  base::test::TestFuture<ActuationTool::ActuationResult> future;
+  feature()->Click(main_frame, action, future.GetCallback());
+
+  auto result = future.Get();
+  EXPECT_FALSE(result.has_value());
+  EXPECT_EQ(result.error().code,
+            ActuationErrorCode::kJavascriptFeatureFailedInJavaScriptExecution);
+  EXPECT_EQ(result.error().message, "Custom JS Error");
+}
+
+TEST_F(ClickToolJavaScriptFeatureTest, JsReturnsErrorWithoutMessage) {
+  web::WebFrame* main_frame = WaitForMainFrame();
+
+  // Override the JS function to return an error dictionary without message.
+  web::test::ExecuteJavaScriptForFeature(
+      web_state(),
+      @"__gCrWeb.getRegisteredApi('click_tool').addFunction('clickByCoordinate'"
+      @", "
+      @"  function() { return {success: false}; }"
+      @"); true;",
+      feature());
+
+  ClickAction action = CreateClickAction();
+
+  base::test::TestFuture<ActuationTool::ActuationResult> future;
+  feature()->Click(main_frame, action, future.GetCallback());
+
+  auto result = future.Get();
+  EXPECT_FALSE(result.has_value());
+  EXPECT_EQ(result.error().code,
+            ActuationErrorCode::kJavascriptFeatureFailedInJavaScriptExecution);
+  EXPECT_EQ(result.error().message, "Unknown error in JS.");
+}
+
+TEST_F(ClickToolJavaScriptFeatureTest, ClickFailure) {
+  int kIframeSize = 100;
+  // Load HTML with an iframe at specific coordinates.
+  NSString* html =
+      [NSString stringWithFormat:@"<html><body>"
+                                 @"<iframe style='position:absolute; left:0px; "
+                                 @"top:0px; width:%dpx; height:%dpx;'></iframe>"
+                                 @"</body></html>",
+                                 kIframeSize, kIframeSize];
+  web::test::LoadHtml(html, web_state());
+  web::WebFrame* main_frame = WaitForMainFrame();
+
+  ClickAction action = CreateClickAction(kIframeSize / 2, kIframeSize / 2);
+
+  base::test::TestFuture<ActuationTool::ActuationResult> future;
+  feature()->Click(main_frame, action, future.GetCallback());
+
+  auto result = future.Get();
+  EXPECT_FALSE(result.has_value());
+  EXPECT_EQ(result.error().code,
+            ActuationErrorCode::kJavascriptFeatureFailedInJavaScriptExecution);
+  EXPECT_EQ(result.error().message, "iframe found at the target coordinates.");
+}
+
+TEST_F(ClickToolJavaScriptFeatureTest, ClickSuccess) {
+  web::WebFrame* main_frame = WaitForMainFrame();
+  ClickAction action = CreateClickAction();
+
+  base::test::TestFuture<ActuationTool::ActuationResult> future;
+  feature()->Click(main_frame, action, future.GetCallback());
+
+  auto result = future.Get();
+  EXPECT_TRUE(result.has_value());
+}
+
+}  // namespace
diff --git a/ios/chrome/browser/intelligence/actuation/model/tools/click_tool_js_unittest.mm b/ios/chrome/browser/intelligence/actuation/model/tools/click_tool_js_unittest.mm
new file mode 100644
index 0000000..336cb4c
--- /dev/null
+++ b/ios/chrome/browser/intelligence/actuation/model/tools/click_tool_js_unittest.mm
@@ -0,0 +1,243 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Foundation/Foundation.h>
+
+#import <set>
+#import <string>
+#import <vector>
+
+#import "base/apple/foundation_util.h"
+#import "base/files/file_util.h"
+#import "base/path_service.h"
+#import "base/strings/stringprintf.h"
+#import "base/strings/sys_string_conversions.h"
+#import "base/test/scoped_feature_list.h"
+#import "ios/web/common/features.h"
+#import "ios/web/public/test/javascript_test.h"
+#import "ios/web/public/test/js_test_util.h"
+#import "net/test/embedded_test_server/embedded_test_server.h"
+#import "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+struct EventInfo {
+  std::string type;
+  int x;
+  int y;
+  bool bubbles;
+  bool cancelable;
+  int button;
+  int detail;
+
+  bool operator==(const EventInfo& other) const {
+    return type == other.type && x == other.x && y == other.y &&
+           bubbles == other.bubbles && cancelable == other.cancelable &&
+           button == other.button && detail == other.detail;
+  }
+};
+
+class ClickToolJavascriptTest : public web::JavascriptTest {
+ public:
+  static constexpr int kButtonX = 50;
+  static constexpr int kButtonY = 50;
+  static constexpr int kIframeX = 50;
+  static constexpr int kIframeY = 200;
+  static constexpr int kEmptyX = 10;
+  static constexpr int kEmptyY = 10;
+  static constexpr int kDevicePixelRatio = 2;
+
+  ClickToolJavascriptTest() {
+    // TODO(crbug.com/483433952): Remove this once it's enabled by default.
+    scoped_feature_list_.InitAndEnableFeature(
+        web::features::kAssertOnJavaScriptErrors);
+    web_view().frame = CGRectMake(0.0, 0.0, 400.0, 400.0);
+  }
+
+ protected:
+  void SetUp() override {
+    web::JavascriptTest::SetUp();
+
+    test_server_.ServeFilesFromSourceDirectory(
+        base::FilePath("ios/testing/data/http_server_files/"));
+    ASSERT_TRUE(test_server_.Start());
+
+    AddGCrWebScript();
+    AddUserScript(@"click_tool");
+
+    ASSERT_TRUE(
+        LoadUrl(GURL(test_server_.GetURL("/actuation/click_tool_test.html"))));
+  }
+
+  std::vector<EventInfo> ExpectedEventsOnClick(int x,
+                                               int y,
+                                               int button,
+                                               int detail) {
+    std::vector<EventInfo> events;
+    events.push_back(
+        {"touchstart", x, y, /*bubbles=*/true, /*cancelable=*/false, 0, 0});
+    events.push_back(
+        {"touchend", x, y, /*bubbles=*/true, /*cancelable=*/false, 0, 0});
+    events.push_back({"mousemove", x, y, /*bubbles=*/true, /*cancelable=*/false,
+                      button, detail});
+    events.push_back({"mousedown", x, y, /*bubbles=*/true, /*cancelable=*/false,
+                      button, detail});
+    events.push_back({"mouseup", x, y, /*bubbles=*/true, /*cancelable=*/false,
+                      button, detail});
+    events.push_back({"click", x, y, /*bubbles=*/true, /*cancelable=*/false,
+                      button, detail});
+    return events;
+  }
+
+  NSDictionary* PerformClick(int x,
+                             int y,
+                             int clickType,
+                             int clickCount,
+                             int pixelType) {
+    NSString* script =
+        [NSString stringWithFormat:
+                      @"__gCrWeb.getRegisteredApi('click_tool').getFunction('"
+                      @"clickByCoordinate')(%d, %d, %d, %d, %d)",
+                      x, y, clickType, clickCount, pixelType];
+
+    id result = web::test::ExecuteJavaScript(web_view(), script);
+    NSDictionary* resultDict = base::apple::ObjCCast<NSDictionary>(result);
+    return resultDict;
+  }
+
+  std::vector<EventInfo> GetCapturedEvents() {
+    NSString* eventsJson = web::test::ExecuteJavaScript(
+        web_view(), @"JSON.stringify(window.capturedEvents)");
+    NSData* data = [eventsJson dataUsingEncoding:NSUTF8StringEncoding];
+    NSArray* eventsArray = [NSJSONSerialization JSONObjectWithData:data
+                                                           options:0
+                                                             error:nil];
+    std::vector<EventInfo> captured_events;
+    for (NSDictionary* eventDict in eventsArray) {
+      EventInfo info;
+      info.type = base::SysNSStringToUTF8(eventDict[@"type"]);
+      info.x = [eventDict[@"x"] intValue];
+      info.y = [eventDict[@"y"] intValue];
+      info.bubbles = [eventDict[@"bubbles"] boolValue];
+      info.cancelable = [eventDict[@"cancelable"] boolValue];
+      info.button = [eventDict[@"button"] intValue];
+      info.detail = [eventDict[@"detail"] intValue];
+      captured_events.push_back(info);
+    }
+    return captured_events;
+  }
+
+  std::string GetButtonText() {
+    id result = web::test::ExecuteJavaScript(
+        web_view(), @"document.getElementById('target_button').innerText");
+    NSString* resultString = base::apple::ObjCCast<NSString>(result);
+    return base::SysNSStringToUTF8(resultString);
+  }
+
+  base::test::ScopedFeatureList scoped_feature_list_;
+  net::EmbeddedTestServer test_server_;
+};
+
+TEST_F(ClickToolJavascriptTest, DensityIndependentPixels_SingleClick_OnButton) {
+  NSDictionary* result = PerformClick(kButtonX, kButtonY, /*clickType=*/1,
+                                      /*clickCount=*/1, /*pixelType=*/1);
+  EXPECT_TRUE([result[@"success"] boolValue]);
+
+  std::vector<EventInfo> expected =
+      ExpectedEventsOnClick(kButtonX, kButtonY, /*button=*/0, /*detail=*/1);
+  std::vector<EventInfo> actual = GetCapturedEvents();
+  EXPECT_EQ(expected, actual);
+  EXPECT_EQ(GetButtonText(), "Clicked");
+}
+
+TEST_F(ClickToolJavascriptTest, DensityIndependentPixels_DoubleClick_OnButton) {
+  NSDictionary* result = PerformClick(kButtonX, kButtonY, /*clickType=*/1,
+                                      /*clickCount=*/2, /*pixelType=*/1);
+  EXPECT_TRUE([result[@"success"] boolValue]);
+
+  std::vector<EventInfo> expected =
+      ExpectedEventsOnClick(kButtonX, kButtonY, /*button=*/0, /*detail=*/1);
+  std::vector<EventInfo> second_click =
+      ExpectedEventsOnClick(kButtonX, kButtonY, /*button=*/0, /*detail=*/2);
+  expected.insert(expected.end(), second_click.begin(), second_click.end());
+  expected.push_back({"dblclick", kButtonX, kButtonY, /*bubbles=*/true,
+                      /*cancelable=*/false, /*button=*/0, /*detail=*/2});
+
+  std::vector<EventInfo> actual = GetCapturedEvents();
+  EXPECT_EQ(expected, actual);
+  EXPECT_EQ(GetButtonText(), "Clicked");
+}
+
+TEST_F(ClickToolJavascriptTest, DensityIndependentPixels_RightClick_OnButton) {
+  NSDictionary* result = PerformClick(kButtonX, kButtonY, /*clickType=*/2,
+                                      /*clickCount=*/1, /*pixelType=*/1);
+  EXPECT_TRUE([result[@"success"] boolValue]);
+
+  std::vector<EventInfo> expected =
+      ExpectedEventsOnClick(kButtonX, kButtonY, /*button=*/2, /*detail=*/1);
+  std::vector<EventInfo> actual = GetCapturedEvents();
+  EXPECT_EQ(expected, actual);
+}
+
+TEST_F(ClickToolJavascriptTest,
+       DensityIndependentPixels_SingleClick_OnIframe_Fails) {
+  NSDictionary* result = PerformClick(kIframeX, kIframeY, /*clickType=*/1,
+                                      /*clickCount=*/1, /*pixelType=*/1);
+  EXPECT_FALSE([result[@"success"] boolValue]);
+  EXPECT_TRUE([result[@"message"]
+      containsString:@"iframe found at the target coordinates."]);
+}
+
+TEST_F(ClickToolJavascriptTest,
+       DensityIndependentPixels_SingleClick_OnEmptySpace) {
+  NSDictionary* result = PerformClick(kEmptyX, kEmptyY, /*clickType=*/1,
+                                      /*clickCount=*/1, /*pixelType=*/1);
+  EXPECT_TRUE([result[@"success"] boolValue]);
+
+  std::vector<EventInfo> expected =
+      ExpectedEventsOnClick(kEmptyX, kEmptyY, /*button=*/0, /*detail=*/1);
+  std::vector<EventInfo> actual = GetCapturedEvents();
+  EXPECT_EQ(expected, actual);
+}
+
+TEST_F(ClickToolJavascriptTest,
+       DensityIndependentPixels_Click_NegativeCoordinates_Fails) {
+  NSDictionary* result = PerformClick(-50, -50, /*clickType=*/1,
+                                      /*clickCount=*/1, /*pixelType=*/1);
+  EXPECT_FALSE([result[@"success"] boolValue]);
+  EXPECT_TRUE([result[@"message"]
+      containsString:@"No element found at the target coordinates."]);
+}
+
+TEST_F(ClickToolJavascriptTest,
+       DensityIndependentPixels_UnknownClickType_DefaultsToLeft) {
+  NSDictionary* result = PerformClick(kButtonX, kButtonY, /*clickType=*/99,
+                                      /*clickCount=*/1, /*pixelType=*/1);
+  EXPECT_TRUE([result[@"success"] boolValue]);
+
+  std::vector<EventInfo> expected =
+      ExpectedEventsOnClick(kButtonX, kButtonY, /*button=*/0, /*detail=*/1);
+  std::vector<EventInfo> actual = GetCapturedEvents();
+  EXPECT_EQ(expected, actual);
+}
+
+TEST_F(ClickToolJavascriptTest, PhysicalPixels_SingleClick_OnButton) {
+  (void)web::test::ExecuteJavaScript(
+      web_view(), [NSString stringWithFormat:@"window.devicePixelRatio = %d;",
+                                             kDevicePixelRatio]);
+
+  int x = kButtonX * kDevicePixelRatio;
+  int y = kButtonY * kDevicePixelRatio;
+  NSDictionary* result = PerformClick(x, y, /*clickType=*/1,
+                                      /*clickCount=*/1, /*pixelType=*/2);
+  EXPECT_TRUE([result[@"success"] boolValue]);
+
+  std::vector<EventInfo> expected =
+      ExpectedEventsOnClick(kButtonX, kButtonY, /*button=*/0, /*detail=*/1);
+  std::vector<EventInfo> actual = GetCapturedEvents();
+  EXPECT_EQ(expected, actual);
+  EXPECT_EQ(GetButtonText(), "Clicked");
+}
+
+}  // namespace
diff --git a/ios/chrome/browser/intelligence/actuation/model/tools/navigate_tool.mm b/ios/chrome/browser/intelligence/actuation/model/tools/navigate_tool.mm
index 2640fbf..025e268 100644
--- a/ios/chrome/browser/intelligence/actuation/model/tools/navigate_tool.mm
+++ b/ios/chrome/browser/intelligence/actuation/model/tools/navigate_tool.mm
@@ -26,8 +26,7 @@
                      ProfileIOS* profile) {
   if (!action.has_tab_id() || !action.has_url()) {
     return base::unexpected(
-        ActuationError{ActuationErrorCode::kToolCreationFailed,
-                       "NavigateAction proto is missing tab id or url."});
+        ActuationError{ActuationErrorCode::kCreationMissingRequiredFields});
   }
 
   BrowserList* browser_list = BrowserListFactory::GetForProfile(profile);
@@ -38,21 +37,18 @@
   Browser* browser = browser_and_index.browser;
   if (tab_index == WebStateList::kInvalidIndex || !browser) {
     return base::unexpected(
-        ActuationError{ActuationErrorCode::kToolCreationFailed,
-                       "Target tab isn't in any Browser."});
+        ActuationError{ActuationErrorCode::kCreationTargetTabNotFound});
   }
 
   WebStateList* web_state_list = browser->GetWebStateList();
   if (!web_state_list) {
     return base::unexpected(
-        ActuationError{ActuationErrorCode::kToolCreationFailed,
-                       "Failed to get WebStateList from browser."});
+        ActuationError{ActuationErrorCode::kCreationMissingWebStateList});
   }
   web::WebState* web_state = web_state_list->GetWebStateAt(tab_index);
   if (!web_state) {
     return base::unexpected(
-        ActuationError{ActuationErrorCode::kToolCreationFailed,
-                       "Failed to get WebState from WebStateList."});
+        ActuationError{ActuationErrorCode::kCreationMissingWebState});
   }
   return std::unique_ptr<NavigateTool>(
       new NavigateTool(action.url(), web_state->GetWeakPtr(), web_state_list,
@@ -63,24 +59,24 @@
 // ActuationService.
 void NavigateTool::Execute(ActuationCallback callback) {
   if (!web_state_ || !web_state_list_ || !url_loader_) {
-    std::move(callback).Run(
-        base::unexpected(ActuationError{ActuationErrorCode::kExecutionFailed,
-                                        "Missing required dependencies."}));
+    std::move(callback).Run(base::unexpected(
+        ActuationError{ActuationErrorCode::kExecutionMissingDependencies}));
     return;
   }
 
   GURL url(url_);
   if (!url.is_valid()) {
     std::move(callback).Run(base::unexpected(
-        ActuationError{ActuationErrorCode::kExecutionFailed, "Invalid URL"}));
+        ActuationError{ActuationErrorCode::kNavigationInvalidURL}));
     return;
   }
 
   // Unrealized WebStates are restored, but not fully functional, tabs that
   // haven't been activated yet. They do not support navigation.
   if (!web_state_->IsRealized()) {
-    std::move(callback).Run(base::unexpected(ActuationError{
-        ActuationErrorCode::kExecutionFailed, "Target tab is not realized."}));
+    std::move(callback).Run(base::unexpected(
+        ActuationError{ActuationErrorCode::kNavigationTabNotRealized}));
+
     return;
   }
 
diff --git a/ios/chrome/browser/intelligence/actuation/model/tools/navigate_tool_unittest.mm b/ios/chrome/browser/intelligence/actuation/model/tools/navigate_tool_unittest.mm
index f439ac0..f19799d 100644
--- a/ios/chrome/browser/intelligence/actuation/model/tools/navigate_tool_unittest.mm
+++ b/ios/chrome/browser/intelligence/actuation/model/tools/navigate_tool_unittest.mm
@@ -78,14 +78,16 @@
       NavigateTool::Create(action.navigate(), profile_.get());
 
   EXPECT_FALSE(result.has_value());
-  EXPECT_EQ(ActuationErrorCode::kToolCreationFailed, result.error().code);
+  EXPECT_EQ(ActuationErrorCode::kCreationMissingRequiredFields,
+            result.error().code);
 
   action.mutable_navigate()->clear_url();
   action.mutable_navigate()->set_tab_id(1);
 
   result = NavigateTool::Create(action.navigate(), profile_.get());
   EXPECT_FALSE(result.has_value());
-  EXPECT_EQ(ActuationErrorCode::kToolCreationFailed, result.error().code);
+  EXPECT_EQ(ActuationErrorCode::kCreationMissingRequiredFields,
+            result.error().code);
 }
 
 TEST_F(NavigateToolTest, Create_NoWebStateForTabId) {
@@ -97,7 +99,8 @@
   base::expected<std::unique_ptr<NavigateTool>, ActuationError> result =
       NavigateTool::Create(action.navigate(), profile_.get());
   EXPECT_FALSE(result.has_value());
-  EXPECT_EQ(ActuationErrorCode::kToolCreationFailed, result.error().code);
+  EXPECT_EQ(ActuationErrorCode::kCreationTargetTabNotFound,
+            result.error().code);
 }
 
 TEST_F(NavigateToolTest, Execute_TabRemovedBeforeExecution) {
@@ -124,7 +127,8 @@
 
   ActuationResult result = future.Get();
   EXPECT_FALSE(result.has_value());
-  EXPECT_EQ(ActuationErrorCode::kExecutionFailed, result.error().code);
+  EXPECT_EQ(ActuationErrorCode::kExecutionMissingDependencies,
+            result.error().code);
 }
 
 TEST_F(NavigateToolTest, Execute_InvalidUrl) {
@@ -147,7 +151,7 @@
 
   ActuationResult result = future.Get();
   ASSERT_FALSE(result.has_value());
-  EXPECT_EQ(ActuationErrorCode::kExecutionFailed, result.error().code);
+  EXPECT_EQ(ActuationErrorCode::kNavigationInvalidURL, result.error().code);
 }
 
 TEST_F(NavigateToolTest, Execute_Success) {
@@ -286,5 +290,5 @@
 
   ActuationResult result = future.Get();
   EXPECT_FALSE(result.has_value());
-  EXPECT_EQ(ActuationErrorCode::kExecutionFailed, result.error().code);
+  EXPECT_EQ(ActuationErrorCode::kNavigationTabNotRealized, result.error().code);
 }
diff --git a/ios/chrome/browser/intelligence/actuation/model/tools/resources/actuation_utils.ts b/ios/chrome/browser/intelligence/actuation/model/tools/resources/actuation_utils.ts
new file mode 100644
index 0000000..fdac42b
--- /dev/null
+++ b/ios/chrome/browser/intelligence/actuation/model/tools/resources/actuation_utils.ts
@@ -0,0 +1,45 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Utility functions for the web actuation tools.
+ */
+
+/**
+ * Returns the element at the given coordinates, accounting for pixel type.
+ *
+ * @param x The x-coordinate.
+ * @param y The y-coordinate.
+ * @param pixelType The type of pixels (0=UNSPECIFIED, 1=DIPS, 2=PHYSICAL).
+ * @return An object containing the target element and the transformed client
+ *     coordinates.
+ */
+export function getElementFromPoint(x: number, y: number, pixelType: number):
+    {element: Element|null, clientX: number, clientY: number} {
+  // See components/optimization_guide/proto/features/common_quality_data.proto
+  // for the definition of PixelType.
+  const PixelType = {
+    UNSPECIFIED: 0,
+    DIPS: 1,
+    PHYSICAL: 2,
+  };
+
+  // UNSPECIFIED and DIPS are assumed to be viewport coordinates (no change).
+  let clientX = x;
+  let clientY = y;
+
+  if (pixelType === PixelType.PHYSICAL) {
+    // PHYSICAL (Hardware Pixels).
+    const dpr = window.devicePixelRatio;
+    // Adjust for device pixel ratio.
+    clientX /= dpr;
+    clientY /= dpr;
+  }
+
+  return {
+    element: document.elementFromPoint(clientX, clientY),
+    clientX: clientX,
+    clientY: clientY,
+  };
+}
diff --git a/ios/chrome/browser/intelligence/actuation/model/tools/resources/click_tool.ts b/ios/chrome/browser/intelligence/actuation/model/tools/resources/click_tool.ts
new file mode 100644
index 0000000..2e20ca03
--- /dev/null
+++ b/ios/chrome/browser/intelligence/actuation/model/tools/resources/click_tool.ts
@@ -0,0 +1,133 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Logic for the WebActuationTool to perform actions on elements.
+ */
+
+import {getElementFromPoint} from '//ios/chrome/browser/intelligence/actuation/model/tools/resources/actuation_utils.js';
+import {CrWebApi, gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+
+/**
+ * Dispatches touch and mouse events to simulate a click on an element.
+ * @param element The target element.
+ * @param clientX The client x-coordinate.
+ * @param clientY The client y-coordinate.
+ * @param clickType The type of click (0=UNKNOWN, 1=LEFT, 2=RIGHT).
+ * @param clickCount The number of clicks (0=UNKNOWN, 1=SINGLE, 2=DOUBLE).
+ * @return an object containing the result of the click attempt.
+ */
+function dispatchClickEvents(
+    element: Element, clientX: number, clientY: number, clickType: number,
+    clickCount: number): {success: boolean, message: string} {
+  // clickType: 1=LEFT, 2=RIGHT maps to 0, 2 in MouseEvent.button.
+  let button = 0;
+  if (clickType === 1) {
+    button = 0;
+  } else if (clickType === 2) {
+    button = 2;
+  }
+
+  const touch = new Touch({
+    identifier: 0,
+    target: element,
+    clientX: clientX,
+    clientY: clientY,
+  });
+
+  const touchEventInit: TouchEventInit = {
+    bubbles: true,
+    cancelable: false,
+    view: window,
+    touches: [touch],
+    targetTouches: [touch],
+    changedTouches: [touch],
+  };
+
+  const dispatchEvents = (detail: number): boolean => {
+    const mouseEventInit: MouseEventInit = {
+      bubbles: true,
+      cancelable: false,
+      view: window,
+      detail: detail,
+      clientX: clientX,
+      clientY: clientY,
+      button: button,
+    };
+    return element.dispatchEvent(
+               new TouchEvent('touchstart', touchEventInit)) &&
+        element.dispatchEvent(new TouchEvent('touchend', touchEventInit)) &&
+        element.dispatchEvent(new MouseEvent('mousemove', mouseEventInit)) &&
+        element.dispatchEvent(new MouseEvent('mousedown', mouseEventInit)) &&
+        element.dispatchEvent(new MouseEvent('mouseup', mouseEventInit)) &&
+        element.dispatchEvent(new MouseEvent('click', mouseEventInit));
+  };
+
+  if (!dispatchEvents(/*detail=*/ 1)) {
+    return {
+      success: false,
+      message: 'Failed to dispatch click event sequence.',
+    };
+  }
+
+  // For double click, dispatch the same series of events followed by a dblclick
+  // event.
+  if (clickCount === 2) {
+    // This event sequence has detail=2 since we've already clicked once.
+    if (!dispatchEvents(/*detail=*/ 2)) {
+      return {
+        success: false,
+        message: 'Failed to dispatch click event sequence again.',
+      };
+    }
+    const dblClickInit: MouseEventInit = {
+      bubbles: true,
+      cancelable: false,
+      view: window,
+      detail: 2,
+      clientX: clientX,
+      clientY: clientY,
+      button: button,
+    };
+    if (!element.dispatchEvent(new MouseEvent('dblclick', dblClickInit))) {
+      return {success: false, message: 'Failed to dispatch dblclick event.'};
+    }
+  }
+
+  return {success: true, message: 'Dispatched touch, mouse, and click events.'};
+}
+
+/**
+ * Simulates a click on a coordinate.
+ * @param x The x-coordinate.
+ * @param y The y-coordinate.
+ * @param clickType The type of click (0=UNKNOWN, 1=LEFT, 2=RIGHT).
+ * @param clickCount The number of clicks (0=UNKNOWN, 1=SINGLE, 2=DOUBLE).
+ * @param pixelType The type of pixels (0=UNSPECIFIED, 1=DIPS, 2=PHYSICAL).
+ * @return an object containing the result of the click attempt.
+ */
+function clickByCoordinate(
+    x: number, y: number, clickType: number, clickCount: number,
+    pixelType: number): {success: boolean, message: string} {
+  const {element, clientX, clientY} = getElementFromPoint(x, y, pixelType);
+
+  if (!element) {
+    return {
+      success: false,
+      message: 'No element found at the target coordinates.',
+    };
+  }
+  if (element.tagName.toUpperCase() === 'IFRAME') {
+    return {
+      success: false,
+      message: 'iframe found at the target coordinates.',
+    };
+  }
+
+  return dispatchClickEvents(element, clientX, clientY, clickType, clickCount);
+}
+
+const clickToolApi = new CrWebApi('click_tool');
+clickToolApi.addFunction('clickByCoordinate', clickByCoordinate);
+gCrWeb.registerApi(clickToolApi);
diff --git a/ios/chrome/browser/intelligence/bwg/metrics/gemini_metrics.h b/ios/chrome/browser/intelligence/bwg/metrics/gemini_metrics.h
index 6effed4d3..61580cb 100644
--- a/ios/chrome/browser/intelligence/bwg/metrics/gemini_metrics.h
+++ b/ios/chrome/browser/intelligence/bwg/metrics/gemini_metrics.h
@@ -73,6 +73,9 @@
 // UMA histogram key for IOS.Gemini.Floaty.HiddenFromSource.
 extern const char kFloatyHiddenFromSourceHistogram[];
 
+// UMA histogram key for IOS.Gemini.Floaty.DismissedState.
+extern const char kFloatyDismissedStateHistogram[];
+
 // Enum for the IOS.Gemini.FRE.PromoAction and IOS.Gemini.FRE.ConsentAction
 // histograms.
 // LINT.IfChange(IOSGeminiFREAction)
@@ -440,8 +443,8 @@
 // Records the floaty transition from collapsed to expanded.
 void RecordFloatyCollapsedToExpanded();
 
-// Records the floaty dismissing while collapsed.
-void RecordFloatyDismissedWhileCollapsed();
+// Records the floaty dismissing with the given state.
+void RecordFloatyDismissedState(ios::provider::GeminiViewState state);
 
 // Records the length of time a floaty is minimized until it is expanded.
 void RecordFloatyMinimizedTime(base::TimeTicks elapsed_minimized_floaty_time);
diff --git a/ios/chrome/browser/intelligence/bwg/metrics/gemini_metrics.mm b/ios/chrome/browser/intelligence/bwg/metrics/gemini_metrics.mm
index 29e5bc29..45daad1 100644
--- a/ios/chrome/browser/intelligence/bwg/metrics/gemini_metrics.mm
+++ b/ios/chrome/browser/intelligence/bwg/metrics/gemini_metrics.mm
@@ -157,6 +157,9 @@
 const char kFloatyHiddenFromSourceHistogram[] =
     "IOS.Gemini.Floaty.HiddenFromSource";
 
+const char kFloatyDismissedStateHistogram[] =
+    "IOS.Gemini.Floaty.DismissedState";
+
 const char kImageRemixContextMenuEntryPointAspectRatioTappedHistogram[] =
     "IOS.Gemini.ImageRemix.ContextMenuEntryPoint.AspectRatio.Tapped";
 
@@ -374,9 +377,16 @@
       IOSGeminiViewStateTransition::kCollapsedToExpanded);
 }
 
-void RecordFloatyDismissedWhileCollapsed() {
-  base::RecordAction(
-      base::UserMetricsAction("MobileGeminiFloatyCollapsedToDismissed"));
+void RecordFloatyDismissedState(ios::provider::GeminiViewState state) {
+  base::UmaHistogramEnumeration(kFloatyDismissedStateHistogram, state);
+
+  if (state == ios::provider::GeminiViewState::kCollapsed) {
+    base::RecordAction(
+        base::UserMetricsAction("MobileGeminiFloatyCollapsedToDismissed"));
+  } else if (state == ios::provider::GeminiViewState::kExpanded) {
+    base::RecordAction(
+        base::UserMetricsAction("MobileGeminiFloatyExpandedToDismissed"));
+  }
 }
 
 void RecordFloatyMinimizedTime(base::TimeTicks elapsed_minimized_floaty_time) {
diff --git a/ios/chrome/browser/intelligence/bwg/model/gemini_browser_agent.mm b/ios/chrome/browser/intelligence/bwg/model/gemini_browser_agent.mm
index 2b7a9e1..007bed6 100644
--- a/ios/chrome/browser/intelligence/bwg/model/gemini_browser_agent.mm
+++ b/ios/chrome/browser/intelligence/bwg/model/gemini_browser_agent.mm
@@ -588,9 +588,7 @@
     return;
   }
 
-  if (last_shown_view_state_ == ios::provider::GeminiViewState::kCollapsed) {
-    RecordFloatyDismissedWhileCollapsed();
-  }
+  RecordFloatyDismissedState(last_shown_view_state_);
 
   is_floaty_invoked_ = false;
   is_hidden_by_keyboard_ = false;
@@ -714,6 +712,14 @@
     }
     [new_active->GetWebViewProxy().scrollViewProxy
         addObserver:scroll_observer_];
+
+    if (!IsGeminiCopresenceZeroStateWithChatHistoryEnabled() ||
+        !is_floaty_invoked_) {
+      return;
+    }
+
+    ios::provider::RequestUIChange(
+        ios::provider::GeminiUIElementType::kZeroState);
   }
 }
 
@@ -918,21 +924,15 @@
   // Disable the page context attachment state based on user prefs.
   PrefService* pref_service = browser_->GetProfile()->GetPrefs();
   if (!pref_service->GetBoolean(prefs::kIOSBWGPageContentSetting)) {
-    // TODO(crbug.com/467341184): Remove the chain assignment after the
-    // migration.
     gemini_page_context.geminiPageContextAttachmentState =
-        gemini_page_context.BWGPageContextAttachmentState =
-            ios::provider::GeminiPageContextAttachmentState::kUserDisabled;
+        ios::provider::GeminiPageContextAttachmentState::kUserDisabled;
   } else {
     // If page context is not disabled by the user, page context is always
     // available and should be attached. Note page context is only partially
     // available (e.g. title, url, favicon) while
     // `GeminiPageContextComputationState` is pending.
-    // TODO(crbug.com/467341184): Remove the chain assignment after the
-    // migration.
     gemini_page_context.geminiPageContextAttachmentState =
-        gemini_page_context.BWGPageContextAttachmentState =
-            ios::provider::GeminiPageContextAttachmentState::kAttached;
+        ios::provider::GeminiPageContextAttachmentState::kAttached;
   }
 }
 
diff --git a/ios/chrome/browser/intelligence/bwg/model/gemini_configuration.h b/ios/chrome/browser/intelligence/bwg/model/gemini_configuration.h
index 8b308af..e08cb00b 100644
--- a/ios/chrome/browser/intelligence/bwg/model/gemini_configuration.h
+++ b/ios/chrome/browser/intelligence/bwg/model/gemini_configuration.h
@@ -65,12 +65,6 @@
 @property(nonatomic, assign) ios::provider::GeminiPageContextAttachmentState
     geminiPageContextAttachmentState;
 
-// The state of the BWG PageContext attachment.
-// TODO(crbug.com/467341184): Remove this property once all callers have
-// migrated.
-@property(nonatomic, assign) ios::provider::GeminiPageContextAttachmentState
-    BWGPageContextAttachmentState;
-
 // The favicon of the attached page. Uses a default icon if it's unavailable.
 @property(nonatomic, strong) UIImage* favicon;
 
diff --git a/ios/chrome/browser/intelligence/bwg/model/gemini_page_context.h b/ios/chrome/browser/intelligence/bwg/model/gemini_page_context.h
index e98f612..e3935c7b 100644
--- a/ios/chrome/browser/intelligence/bwg/model/gemini_page_context.h
+++ b/ios/chrome/browser/intelligence/bwg/model/gemini_page_context.h
@@ -35,12 +35,6 @@
 @property(nonatomic, assign) ios::provider::GeminiPageContextAttachmentState
     geminiPageContextAttachmentState;
 
-// The state of the BWG PageContext attachment.
-// TODO(crbug.com/467341184): Remove this property once all callers have
-// migrated.
-@property(nonatomic, assign) ios::provider::GeminiPageContextAttachmentState
-    BWGPageContextAttachmentState;
-
 // The favicon of the attached page. Uses a default icon if it's unavailable.
 @property(nonatomic, strong) UIImage* favicon;
 
diff --git a/ios/chrome/browser/intelligence/proto_wrappers/annotated_page_content_extraction_utils.mm b/ios/chrome/browser/intelligence/proto_wrappers/annotated_page_content_extraction_utils.mm
index e58de6c..3dc2c1bb 100644
--- a/ios/chrome/browser/intelligence/proto_wrappers/annotated_page_content_extraction_utils.mm
+++ b/ios/chrome/browser/intelligence/proto_wrappers/annotated_page_content_extraction_utils.mm
@@ -55,6 +55,23 @@
 constexpr char kSelectedTextKey[] = "selectedText";
 constexpr char kFocusedDomNodeIdKey[] = "focusedDomNodeId";
 constexpr char kDocumentIdKey[] = "documentId";
+constexpr char kFormControlDataKey[] = "formControlData";
+constexpr char kFormControlTypeKey[] = "formControlType";
+constexpr char kFieldNameKey[] = "fieldName";
+constexpr char kFieldValueKey[] = "fieldValue";
+constexpr char kSelectOptionsKey[] = "selectOptions";
+constexpr char kOptionValueKey[] = "value";
+constexpr char kOptionTextKey[] = "text";
+constexpr char kIsSelectedKey[] = "isSelected";
+constexpr char kIsDisabledKey[] = "disabled";
+constexpr char kPlaceholderKey[] = "placeholder";
+constexpr char kIsCheckedKey[] = "isChecked";
+constexpr char kIsRequiredKey[] = "isRequired";
+constexpr char kIsReadonlyKey[] = "isReadonly";
+constexpr char kRedactionDecisionKey[] = "redactionDecision";
+constexpr char kFormDataKey[] = "formData";
+constexpr char kFormNameKey[] = "formName";
+constexpr char kFormActionUrlKey[] = "actionUrl";
 
 // Reads a JS number (double) from a `dict` stored under `key`.
 std::optional<int> ReadJsNumber(const base::DictValue& dict, const char* key) {
@@ -257,6 +274,106 @@
   }
 }
 
+// Populates the form control data of the `destination_node` from the
+// `form_control_data` content.
+void PopulateFormControlData(
+    const base::DictValue& form_control_data,
+    optimization_guide::proto::ContentNode* destination_node) {
+  optimization_guide::proto::FormControlData* proto_form_control_data =
+      destination_node->mutable_content_attributes()
+          ->mutable_form_control_data();
+
+  if (std::optional<int> form_control_type =
+          ReadJsNumber(form_control_data, kFormControlTypeKey)) {
+    if (optimization_guide::proto::FormControlType_IsValid(
+            *form_control_type)) {
+      proto_form_control_data->set_form_control_type(
+          static_cast<optimization_guide::proto::FormControlType>(
+              *form_control_type));
+    }
+  }
+
+  if (const std::string* field_name =
+          form_control_data.FindString(kFieldNameKey)) {
+    proto_form_control_data->set_field_name(*field_name);
+  }
+
+  if (const std::string* field_value =
+          form_control_data.FindString(kFieldValueKey)) {
+    proto_form_control_data->set_field_value(*field_value);
+  }
+
+  if (const std::string* placeholder =
+          form_control_data.FindString(kPlaceholderKey)) {
+    proto_form_control_data->set_placeholder(*placeholder);
+  }
+
+  proto_form_control_data->set_is_checked(
+      form_control_data.FindBool(kIsCheckedKey).value_or(false));
+
+  proto_form_control_data->set_is_required(
+      form_control_data.FindBool(kIsRequiredKey).value_or(false));
+
+  if (form_control_data.FindBool(kIsReadonlyKey).value_or(false)) {
+    // Temporarily map readonly to disabled. This is a lossy workaround that
+    // preserves "do not edit" intent for consumers that only read proto data.
+    // TODO(crbug.com/481361478): Add readonly field to FormControlData proto.
+    destination_node->mutable_content_attributes()
+        ->mutable_interaction_info()
+        ->set_is_disabled(true);
+  }
+
+  if (std::optional<int> redaction_decision =
+          ReadJsNumber(form_control_data, kRedactionDecisionKey)) {
+    if (optimization_guide::proto::RedactionDecision_IsValid(
+            *redaction_decision)) {
+      proto_form_control_data->set_redaction_decision(
+          static_cast<optimization_guide::proto::RedactionDecision>(
+              *redaction_decision));
+    }
+  }
+
+  if (const base::ListValue* select_options =
+          form_control_data.FindList(kSelectOptionsKey)) {
+    for (const base::Value& option_value : *select_options) {
+      if (option_value.is_dict()) {
+        const base::DictValue* option_dict = &option_value.GetDict();
+        optimization_guide::proto::SelectOption* proto_select_option =
+            proto_form_control_data->add_select_options();
+
+        if (const std::string* value =
+                option_dict->FindString(kOptionValueKey)) {
+          proto_select_option->set_value(*value);
+        }
+        if (const std::string* text = option_dict->FindString(kOptionTextKey)) {
+          proto_select_option->set_text(*text);
+        }
+        proto_select_option->set_is_selected(
+            option_dict->FindBool(kIsSelectedKey).value_or(false));
+        proto_select_option->set_is_disabled(
+            option_dict->FindBool(kIsDisabledKey).value_or(false));
+      }
+    }
+  }
+}
+
+// Populates the form data of the `destination_node` from the `form_data`
+// content.
+void PopulateFormInfo(
+    const base::DictValue& form_data,
+    optimization_guide::proto::ContentNode* destination_node) {
+  optimization_guide::proto::FormInfo* proto_form_info =
+      destination_node->mutable_content_attributes()->mutable_form_data();
+
+  if (const std::string* form_name = form_data.FindString(kFormNameKey)) {
+    proto_form_info->set_form_name(*form_name);
+  }
+
+  if (const std::string* action_url = form_data.FindString(kFormActionUrlKey)) {
+    proto_form_info->set_action_url(*action_url);
+  }
+}
+
 }  // namespace
 
 void PopulateAPCNodeFromContentTree(
@@ -365,6 +482,22 @@
       }
       break;
     }
+    case optimization_guide::proto::CONTENT_ATTRIBUTE_FORM: {
+      const base::DictValue* form_data =
+          content_attributes->FindDict(kFormDataKey);
+      if (form_data) {
+        PopulateFormInfo(*form_data, destination_node);
+      }
+      break;
+    }
+    case optimization_guide::proto::CONTENT_ATTRIBUTE_FORM_CONTROL: {
+      const base::DictValue* form_control_data =
+          content_attributes->FindDict(kFormControlDataKey);
+      if (form_control_data) {
+        PopulateFormControlData(*form_control_data, destination_node);
+      }
+      break;
+    }
     default:
       break;
   }
diff --git a/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper_unittest.mm b/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper_unittest.mm
index 1bf1c08..ef56282 100644
--- a/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper_unittest.mm
+++ b/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper_unittest.mm
@@ -3391,6 +3391,112 @@
   }
 }
 
+// Tests the extraction of form control attributes (input, textarea, select,
+// button).
+TEST_P(PageContextWrapperTest,
+       PopulatePageContext_RichExtraction_FormControlData) {
+  if (!IsRefactored()) {
+    GTEST_SKIP() << "ApcV2 not supported for the non-refactored APC wrapper";
+  }
+
+  auto page_structure = HtmlPage(
+      "Forms", RawHtml("<html><body><form name=\"f1\" action='/submit'>"
+                       "  <input type=\"text\" name=\"t1\" value=\"v1\" "
+                       "required placeholder=\"p1\">"
+                       "  <input type=\"text\" name=\"t2\" value=\"v2\" "
+                       "readonly>"
+                       "  <input type=\"checkbox\" checked>"
+                       "  <select name=\"s1\">"
+                       "    <option value=\"o1\" selected>O1</option>"
+                       "    <option disabled>O2</option>"
+                       "  </select>"
+                       "  <button type=\"submit\">Submit</button>"
+                       "  <textarea name=\"texta\">text contents</textarea>"
+                       "</form></body></html>"));
+  std::string main_html = page_helper_->Build(page_structure);
+  web::test::LoadHtml(base::SysUTF8ToNSString(main_html),
+                      test_server_.GetURL(kMainPagePath), web_state());
+
+  PageContextWrapperConfig config =
+      PageContextWrapperConfigBuilder().SetUseRichExtraction(true).Build();
+
+  PageContextWrapperCallbackResponse response = RunPageContextWrapperWithConfig(
+      web_state(), config, ^(PageContextWrapper* wrapper) {
+        wrapper.shouldGetAnnotatedPageContent = YES;
+      });
+
+  ASSERT_TRUE(response.has_value());
+  std::unique_ptr<optimization_guide::proto::PageContext> page_context =
+      std::move(response.value());
+
+  ASSERT_TRUE(page_context);
+  ASSERT_TRUE(page_context->has_annotated_page_content());
+
+  const auto& annotated_page_content = page_context->annotated_page_content();
+  const auto& root_node = annotated_page_content.root_node();
+
+  ASSERT_EQ(root_node.children_nodes_size(), 1);
+  const auto& form_node = root_node.children_nodes(0);
+
+  EXPECT_TRUE(form_node.content_attributes().has_form_data());
+  EXPECT_EQ(form_node.content_attributes().form_data().form_name(), "f1");
+  // The full URL depends on the test server port, so we check the suffix.
+  EXPECT_TRUE(base::EndsWith(
+      form_node.content_attributes().form_data().action_url(), "/submit"));
+
+  ASSERT_EQ(form_node.children_nodes_size(), 6);
+  const auto* input_text_node = &form_node.children_nodes(0);
+  const auto* input_readonly_node = &form_node.children_nodes(1);
+  const auto* input_checkbox_node = &form_node.children_nodes(2);
+  const auto* select_node = &form_node.children_nodes(3);
+  const auto* button_node = &form_node.children_nodes(4);
+  const auto* textarea_node = &form_node.children_nodes(5);
+
+  ASSERT_TRUE(input_text_node);
+  const auto& fc_text =
+      input_text_node->content_attributes().form_control_data();
+  EXPECT_EQ(fc_text.field_name(), "t1");
+  EXPECT_EQ(fc_text.field_value(), "v1");
+  EXPECT_TRUE(fc_text.is_required());
+  EXPECT_FALSE(
+      input_text_node->content_attributes().interaction_info().is_disabled());
+  EXPECT_EQ(fc_text.placeholder(), "p1");
+
+  ASSERT_TRUE(input_readonly_node);
+  const auto& fc_readonly =
+      input_readonly_node->content_attributes().form_control_data();
+  EXPECT_EQ(fc_readonly.field_name(), "t2");
+  EXPECT_EQ(fc_readonly.field_value(), "v2");
+  EXPECT_FALSE(fc_readonly.is_required());
+  EXPECT_TRUE(input_readonly_node->content_attributes().has_interaction_info());
+  EXPECT_TRUE(input_readonly_node->content_attributes()
+                  .interaction_info()
+                  .is_disabled());
+
+  ASSERT_TRUE(input_checkbox_node);
+  const auto& fc_checkbox =
+      input_checkbox_node->content_attributes().form_control_data();
+  EXPECT_TRUE(fc_checkbox.is_checked());
+
+  ASSERT_TRUE(select_node);
+  const auto& fc_select = select_node->content_attributes().form_control_data();
+  EXPECT_EQ(fc_select.field_name(), "s1");
+  ASSERT_EQ(fc_select.select_options_size(), 2);
+  EXPECT_EQ(fc_select.select_options(0).value(), "o1");
+  EXPECT_EQ(fc_select.select_options(0).text(), "O1");
+  EXPECT_TRUE(fc_select.select_options(0).is_selected());
+  EXPECT_EQ(fc_select.select_options(1).value(), "O2");
+  EXPECT_EQ(fc_select.select_options(1).text(), "O2");
+  EXPECT_TRUE(fc_select.select_options(1).is_disabled());
+
+  ASSERT_TRUE(button_node);
+
+  ASSERT_TRUE(textarea_node);
+  const auto& fc_textarea =
+      textarea_node->content_attributes().form_control_data();
+  EXPECT_EQ(fc_textarea.field_name(), "texta");
+}
+
 // Tests that Canvas Metadata is extracted correctly.
 TEST_P(PageContextWrapperTest, PopulatePageContext_RichExtraction_Canvas) {
   if (!IsRefactored()) {
diff --git a/ios/chrome/browser/intelligence/proto_wrappers/resources/annotated_page_content_extraction.ts b/ios/chrome/browser/intelligence/proto_wrappers/resources/annotated_page_content_extraction.ts
index 04d554f..60e662ef 100644
--- a/ios/chrome/browser/intelligence/proto_wrappers/resources/annotated_page_content_extraction.ts
+++ b/ios/chrome/browser/intelligence/proto_wrappers/resources/annotated_page_content_extraction.ts
@@ -4,8 +4,8 @@
 
 import {APC_NODE_DEPTH_COST, getRemoteFrameRemoteToken, MAX_APC_RESPONSE_DEPTH, NONCE_ATTR} from '//ios/chrome/browser/intelligence/proto_wrappers/resources/common.js';
 import {getNodeId, getOrCreateNodeId} from '//ios/chrome/browser/intelligence/proto_wrappers/resources/dom_node_ids.js';
-import {PageContentAnchorRel, PageContentAnnotatedRole, PageContentAttributeType, PageContentTextSize} from '//ios/chrome/browser/intelligence/proto_wrappers/resources/page_content_types.js';
-import type {PageContent, PageContentAttributes, PageContentFrameData, PageContentFrameInteractionInfo, PageContentNode, PageContentPageInteractionInfo} from '//ios/chrome/browser/intelligence/proto_wrappers/resources/page_content_types.js';
+import {FormControlType, PageContentAnchorRel, PageContentAnnotatedRole, PageContentAttributeType, PageContentRedactionDecision, PageContentTextSize} from '//ios/chrome/browser/intelligence/proto_wrappers/resources/page_content_types.js';
+import type {PageContent, PageContentAttributes, PageContentFormControlData, PageContentFormData, PageContentFrameData, PageContentFrameInteractionInfo, PageContentNode, PageContentPageInteractionInfo} from '//ios/chrome/browser/intelligence/proto_wrappers/resources/page_content_types.js';
 
 // Set of DOM Node IDs that are considered interactive (focused, selection
 // start/end). These nodes should be included in the APC tree even if they are
@@ -114,6 +114,29 @@
 // The constant length of the masked text.
 const MASKED_TEXT_LENGTH = 7;
 
+// Form control types.
+const PASSWORD_TYPE = 'password';
+const BUTTON_TYPE = 'button';
+const CHECKBOX_TYPE = 'checkbox';
+const COLOR_TYPE = 'color';
+const DATE_TYPE = 'date';
+const DATETIME_LOCAL_TYPE = 'datetime-local';
+const EMAIL_TYPE = 'email';
+const FILE_TYPE = 'file';
+const HIDDEN_TYPE = 'hidden';
+const IMAGE_TYPE = 'image';
+const MONTH_TYPE = 'month';
+const NUMBER_TYPE = 'number';
+const RADIO_TYPE = 'radio';
+const RANGE_TYPE = 'range';
+const RESET_TYPE = 'reset';
+const SEARCH_TYPE = 'search';
+const SUBMIT_TYPE = 'submit';
+const TELEPHONE_TYPE = 'tel';
+const TIME_TYPE = 'time';
+const URL_TYPE = 'url';
+const WEEK_TYPE = 'week';
+const TEXT_TYPE = 'text';
 
 const BASIC_CONTENT_ATTRIBUTES: PageContentAttributes = {
   attributeType: PageContentAttributeType.UNKNOWN,
@@ -210,6 +233,95 @@
 }
 
 /**
+ * Maps an element to its corresponding FormControlType.
+ *
+ * @param element The element to map.
+ * @return The corresponding FormControlType.
+ */
+function getFormControlType(element: HTMLElement): FormControlType|undefined {
+  const tagName = element.tagName;
+
+  if (tagName === TAG_BUTTON) {
+    const type = (element as HTMLButtonElement).type;
+    switch (type) {
+      case 'submit':
+        return FormControlType.BUTTON_SUBMIT;
+      case 'reset':
+        return FormControlType.BUTTON_RESET;
+      case 'button':
+      default:
+        return FormControlType.BUTTON_BUTTON;
+    }
+  }
+
+  if (tagName === TAG_INPUT) {
+    const type = (element as HTMLInputElement).type;
+    switch (type) {
+      case BUTTON_TYPE:
+        return FormControlType.INPUT_BUTTON;
+      case CHECKBOX_TYPE:
+        return FormControlType.INPUT_CHECKBOX;
+      case COLOR_TYPE:
+        return FormControlType.INPUT_COLOR;
+      case DATE_TYPE:
+        return FormControlType.INPUT_DATE;
+      case DATETIME_LOCAL_TYPE:
+        return FormControlType.INPUT_DATETIME_LOCAL;
+      case EMAIL_TYPE:
+        return FormControlType.INPUT_EMAIL;
+      case FILE_TYPE:
+        return FormControlType.INPUT_FILE;
+      case HIDDEN_TYPE:
+        return FormControlType.INPUT_HIDDEN;
+      case IMAGE_TYPE:
+        return FormControlType.INPUT_IMAGE;
+      case MONTH_TYPE:
+        return FormControlType.INPUT_MONTH;
+      case NUMBER_TYPE:
+        return FormControlType.INPUT_NUMBER;
+      case PASSWORD_TYPE:
+        return FormControlType.INPUT_PASSWORD;
+      case RADIO_TYPE:
+        return FormControlType.INPUT_RADIO;
+      case RANGE_TYPE:
+        return FormControlType.INPUT_RANGE;
+      case RESET_TYPE:
+        return FormControlType.INPUT_RESET;
+      case SEARCH_TYPE:
+        return FormControlType.INPUT_SEARCH;
+      case SUBMIT_TYPE:
+        return FormControlType.INPUT_SUBMIT;
+      case TELEPHONE_TYPE:
+        return FormControlType.INPUT_TELEPHONE;
+      case TIME_TYPE:
+        return FormControlType.INPUT_TIME;
+      case URL_TYPE:
+        return FormControlType.INPUT_URL;
+      case WEEK_TYPE:
+        return FormControlType.INPUT_WEEK;
+      case TEXT_TYPE:
+      default:
+        // Standard default type when no type is specified.
+        return FormControlType.INPUT_TEXT;
+    }
+  }
+
+  if (tagName === TAG_SELECT) {
+    if ((element as HTMLSelectElement).multiple) {
+      return FormControlType.SELECT_MULTIPLE;
+    }
+    return FormControlType.SELECT_ONE;
+  }
+
+  if (tagName === TAG_TEXTAREA) {
+    return FormControlType.TEXT_AREA;
+  }
+
+  // Fallback, though we shouldn't reach here for form controls.
+  return undefined;
+}
+
+/**
  * Extracts the relationships (rel attribute) from an anchor element.
  *
  * @param anchorElement The anchor element to extract relationships from.
@@ -246,6 +358,24 @@
   return result;
 }
 
+/**
+ * Extracts form specific content attributes from a given DOM element.
+ *
+ * @param form The form element to process.
+ * @return The populated PageContentFormData.
+ */
+function getFormData(form: HTMLFormElement): PageContentFormData {
+  const formData: PageContentFormData = {};
+  if (form.name) {
+    formData.formName = form.name;
+  }
+  if (form.action) {
+    formData.actionUrl = form.action;
+  }
+  return formData;
+}
+
+
 // TODO(crbug.com/480945289): Complete this function as more data becomes
 // available throughout iterations.
 /**
@@ -534,6 +664,102 @@
 }
 
 /**
+ * Extracts form control specific content attributes from a given DOM element.
+ * Handles inputs, textareas, selects, and buttons.
+ *
+ * @param domNode The element to process.
+ * @param tagName The tag name of the element.
+ * @return The populated PageContentFormControlData.
+ */
+function getFormControlData(
+    domNode: HTMLElement, tagName: string): PageContentFormControlData {
+  // There must be a type returned, throw an exception if not.
+  const formControlType = getFormControlType(domNode)!;
+  const formControlData: PageContentFormControlData = {
+    formControlType: formControlType,
+    selectOptions: [],
+    isChecked: false,
+    isRequired: false,
+    // TODO(crbug.com/485211722): Set redaction decision for Autofill.
+    redactionDecision: PageContentRedactionDecision.NO_REDACTION_NECESSARY,
+  };
+
+  const name = (domNode as HTMLInputElement).name;
+  if (name !== undefined && name !== '') {
+    formControlData.fieldName = name;
+  }
+
+  const value = (domNode as HTMLInputElement).value;
+  if (value !== undefined) {
+    // TODO(crbug.com/485211722): Complete implementation once redaction
+    // decision is fully available.
+    // Exclude password field value mirroring Blink's logic.
+    // For now, only extract value if type != password.
+    // TAG_TEXTAREA and TAG_SELECT do not support the 'type' attribute to
+    // designate a password field, so we consider their values safe to extract
+    // (unless they are custom passwords, which is handled separately).
+    if (tagName !== TAG_INPUT ||
+        (domNode as HTMLInputElement).type !== PASSWORD_TYPE) {
+      formControlData.fieldValue = value;
+    }
+  }
+
+  formControlData.isRequired = (domNode as HTMLInputElement).required ?? false;
+
+  // Handle aria-required override.
+  if (!formControlData.isRequired &&
+      domNode.getAttribute('aria-required') === 'true') {
+    formControlData.isRequired = true;
+  }
+
+  const isReadonly = (domNode as HTMLInputElement).readOnly ?? false;
+  formControlData.isReadonly = isReadonly;
+
+  // Handle aria-readonly override.
+  if (!isReadonly && domNode.getAttribute('aria-readonly') === 'true') {
+    formControlData.isReadonly = true;
+  }
+
+  // Checkbox and Radio.
+  if (tagName === TAG_INPUT) {
+    const inputElement = domNode as HTMLInputElement;
+    if (inputElement.type === 'checkbox' || inputElement.type === 'radio') {
+      formControlData.isChecked = inputElement.checked;
+    }
+  }
+
+  // Placeholder.
+  const placeholder = (domNode as HTMLInputElement).placeholder;
+  if (placeholder) {
+    formControlData.placeholder = placeholder;
+  } else {
+    const ariaPlaceholder = domNode.getAttribute('aria-placeholder');
+    if (ariaPlaceholder) {
+      formControlData.placeholder = ariaPlaceholder;
+    }
+  }
+
+  // Select Options.
+  if (tagName === TAG_SELECT) {
+    const selectElement = domNode as HTMLSelectElement;
+    for (const option of Array.from(selectElement.options)) {
+      let text = option.text;
+      if (!text) {
+        text = option.label;
+      }
+      formControlData.selectOptions.push({
+        value: option.value,
+        text: text,
+        isSelected: option.selected,
+        disabled: option.disabled,
+      });
+    }
+  }
+
+  return formControlData as PageContentFormControlData;
+}
+
+/**
  * Returns basic content for an element node that is not a generic
  * container based on its tag name.
  *
@@ -643,19 +869,22 @@
         contentAttributes: {
           ...BASIC_CONTENT_ATTRIBUTES,
           attributeType: PageContentAttributeType.FORM,
+          formData: getFormData(domNode as HTMLFormElement),
         },
       };
     case TAG_INPUT:
     case TAG_TEXTAREA:
     case TAG_SELECT:
-    case TAG_BUTTON:
+    case TAG_BUTTON: {
       return {
         childrenNodes: [],
         contentAttributes: {
           ...BASIC_CONTENT_ATTRIBUTES,
           attributeType: PageContentAttributeType.FORM_CONTROL,
+          formControlData: getFormControlData(domNode, tagName),
         },
       };
+    }
     case TAG_H1:
     case TAG_H2:
     case TAG_H3:
diff --git a/ios/chrome/browser/intelligence/proto_wrappers/resources/page_content_types.ts b/ios/chrome/browser/intelligence/proto_wrappers/resources/page_content_types.ts
index b669096..9543e87 100644
--- a/ios/chrome/browser/intelligence/proto_wrappers/resources/page_content_types.ts
+++ b/ios/chrome/browser/intelligence/proto_wrappers/resources/page_content_types.ts
@@ -350,6 +350,7 @@
   placeholder?: string;
   isChecked: boolean;
   isRequired: boolean;
+  isReadonly?: boolean;
   redactionDecision: PageContentRedactionDecision;
 }
 
diff --git a/ios/chrome/browser/shared/public/features/BUILD.gn b/ios/chrome/browser/shared/public/features/BUILD.gn
index f5268ec1..ac04d00 100644
--- a/ios/chrome/browser/shared/public/features/BUILD.gn
+++ b/ios/chrome/browser/shared/public/features/BUILD.gn
@@ -37,11 +37,9 @@
     "//components/password_manager/core/common:features",
     "//components/segmentation_platform/public",
     "//components/variations",
-    "//components/version_info:channel",
     "//ios/chrome/browser/flags:system_flags",
     "//ios/chrome/browser/memory/model:features",
     "//ios/chrome/browser/safety_check/model:constants",
     "//ios/chrome/browser/shared/public/features",
-    "//ios/chrome/common",
   ]
 }
diff --git a/ios/chrome/browser/shared/public/features/system_flags.h b/ios/chrome/browser/shared/public/features/system_flags.h
index faaf5aa0..217dbbd 100644
--- a/ios/chrome/browser/shared/public/features/system_flags.h
+++ b/ios/chrome/browser/shared/public/features/system_flags.h
@@ -176,9 +176,6 @@
 // there is no alternative URL specified.
 NSString* GetLensResultPanelGwsURL();
 
-// Whether the unified flags menu should be shown in the Lens HUD overflow menu.
-bool EnableLensUnifiedFlagsMenu();
-
 // Returns true if Composebox AIM eligibility should be disabled.
 bool ShouldForceDisableComposeboxAIM();
 
diff --git a/ios/chrome/browser/shared/public/features/system_flags.mm b/ios/chrome/browser/shared/public/features/system_flags.mm
index 29b755e..eb4404c 100644
--- a/ios/chrome/browser/shared/public/features/system_flags.mm
+++ b/ios/chrome/browser/shared/public/features/system_flags.mm
@@ -18,12 +18,10 @@
 #import "components/password_manager/core/common/password_manager_features.h"
 #import "components/segmentation_platform/public/constants.h"
 #import "components/variations/variations_associated_data.h"
-#import "components/version_info/channel.h"
 #import "ios/chrome/browser/flags/chrome_switches.h"
 #import "ios/chrome/browser/memory/model/features.h"
 #import "ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager_constants.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
-#import "ios/chrome/common/channel_info.h"
 
 namespace {
 
@@ -69,7 +67,6 @@
 NSString* const kInactiveTabsTestMode = @"InactiveTabsTestMode";
 NSString* const kAsyncStartupOverrideResponse = @"AsyncStartupOverrideResponse";
 NSString* const kLensResultPanelGwsURL = @"LensResultPanelGwsURL";
-NSString* const kLensUnifiedLensMenu = @"LensUnifiedFlagsMenu";
 NSString* const kForceDisableAIMEligibility = @"ForceDisableAIMEligibility";
 NSString* const kForceDisableCreateImagesEligibility =
     @"ForceDisableCreateImagesEligibility";
@@ -371,19 +368,6 @@
       stringForKey:kLensResultPanelGwsURL];
 }
 
-bool EnableLensUnifiedFlagsMenu() {
-  version_info::Channel channel = GetChannel();
-  // Enable for only internal builds; Beta is public.
-  if (channel == version_info::Channel::UNKNOWN ||
-      channel == version_info::Channel::DEV ||
-      channel == version_info::Channel::CANARY) {
-    return true;
-  }
-
-  return
-      [[NSUserDefaults standardUserDefaults] boolForKey:kLensUnifiedLensMenu];
-}
-
 bool ShouldForceDisableComposeboxAIM() {
   return [[NSUserDefaults standardUserDefaults]
       boolForKey:kForceDisableAIMEligibility];
diff --git a/ios/chrome/browser/web/model/BUILD.gn b/ios/chrome/browser/web/model/BUILD.gn
index 7a52fbc7..883bb15e 100644
--- a/ios/chrome/browser/web/model/BUILD.gn
+++ b/ios/chrome/browser/web/model/BUILD.gn
@@ -291,6 +291,8 @@
     "//ios/chrome/browser/flags:system_flags",
     "//ios/chrome/browser/https_upgrades/model",
     "//ios/chrome/browser/infobars/ui_bundled/coordinators",
+    "//ios/chrome/browser/intelligence/actuation/model/tools:java_script_features",
+    "//ios/chrome/browser/intelligence/features",
     "//ios/chrome/browser/intelligence/proto_wrappers:page_context_extractor_feature",
     "//ios/chrome/browser/link_to_text/model",
     "//ios/chrome/browser/metrics/model:accessor",
diff --git a/ios/chrome/browser/web/model/DEPS b/ios/chrome/browser/web/model/DEPS
index 65c743d1..1439724 100644
--- a/ios/chrome/browser/web/model/DEPS
+++ b/ios/chrome/browser/web/model/DEPS
@@ -17,6 +17,7 @@
   "+ios/chrome/browser/geolocation/model/geolocation_manager.h",
   "+ios/chrome/browser/https_upgrades/model",
   "+ios/chrome/browser/infobars/model",
+  "+ios/chrome/browser/intelligence/actuation/model/tools",
   "+ios/chrome/browser/intelligence/bwg/utils/bwg_constants.h",
   "+ios/chrome/browser/intelligence/features/features.h",
   "+ios/chrome/browser/intelligence/proto_wrappers/page_context_extractor_java_script_feature.h",
diff --git a/ios/chrome/browser/web/model/chrome_web_client.mm b/ios/chrome/browser/web/model/chrome_web_client.mm
index 6acd7cc..6396cbc 100644
--- a/ios/chrome/browser/web/model/chrome_web_client.mm
+++ b/ios/chrome/browser/web/model/chrome_web_client.mm
@@ -46,6 +46,8 @@
 #import "ios/chrome/browser/enterprise/connectors/reporting/ios_reporting_event_router_factory.h"
 #import "ios/chrome/browser/flags/chrome_switches.h"
 #import "ios/chrome/browser/https_upgrades/model/https_upgrade_service_factory.h"
+#import "ios/chrome/browser/intelligence/actuation/model/tools/click_tool_java_script_feature.h"
+#import "ios/chrome/browser/intelligence/features/features.h"
 #import "ios/chrome/browser/intelligence/proto_wrappers/page_context_extractor_java_script_feature.h"
 #import "ios/chrome/browser/link_to_text/model/link_to_text_java_script_feature.h"
 #import "ios/chrome/browser/ntp/model/browser_policy_new_tab_page_rewriter.h"
@@ -444,6 +446,10 @@
   features.push_back(ChooseFileJavaScriptFeature::GetInstance());
   features.push_back(PageContextExtractorJavaScriptFeature::GetInstance());
 
+  if (base::FeatureList::IsEnabled(kActuationTools)) {
+    features.push_back(ClickToolJavaScriptFeature::GetInstance());
+  }
+
   features.push_back(
       SupervisedUserInterstitialJavaScriptFeature::GetInstance());
 
diff --git a/ios/public/provider/chrome/browser/bwg/bwg_api.h b/ios/public/provider/chrome/browser/bwg/bwg_api.h
index 23202e90..1f07684 100644
--- a/ios/public/provider/chrome/browser/bwg/bwg_api.h
+++ b/ios/public/provider/chrome/browser/bwg/bwg_api.h
@@ -82,11 +82,9 @@
   kEnterpriseDisabled,
 };
 
-// TODO(crbug.com/467341184): Remove this alias once all callers have migrated.
-using BWGPageContextAttachmentState = GeminiPageContextAttachmentState;
-
 // Enum representing the Gemini view state.
 // This needs to stay in sync with GCRGeminiViewState (and its SDK counterpart).
+// LINT.IfChange(GeminiViewState)
 enum class GeminiViewState {
   // The Gemini view state is unknown.
   kUnknown,
@@ -100,7 +98,9 @@
   kCollapsed,
   // The Gemini view is expanded.
   kExpanded,
+  kMaxValue = kExpanded,
 };
+// LINT.ThenChange(/tools/metrics/histograms/metadata/ios/enums.xml:GeminiViewState)
 
 // Enum representing the UI element type for which a change is requested.
 // This needs to stay in sync with GCRGeminiUIElementType (and its SDK
diff --git a/ios/testing/data/http_server_files/actuation/click_tool_test.html b/ios/testing/data/http_server_files/actuation/click_tool_test.html
new file mode 100644
index 0000000..5121fad
--- /dev/null
+++ b/ios/testing/data/http_server_files/actuation/click_tool_test.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<!--
+Copyright 2026 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+This file is used to test the ClickToolJavaScriptFeature.
+It captures touch and mouse events and exposes them via `window.capturedEvents`.
+The button with id 'target_button' also changes its text to 'Clicked' when clicked.
+-->
+<html>
+  <head>
+  <script>
+    window.capturedEvents = [];
+    function record(e) {
+      let x = e.clientX;
+      let y = e.clientY;
+      if (e.type.startsWith('touch')) {
+        const touch = e.touches[0];
+        if (touch) {
+          x = touch.clientX;
+          y = touch.clientY;
+        }
+      }
+      const info = {
+        type: e.type,
+        x: x,
+        y: y,
+        bubbles: e.bubbles,
+        cancelable: e.cancelable,
+        button: e.button,
+        detail: e.detail
+      };
+      window.capturedEvents.push(info);
+    }
+    const events = ['touchstart', 'touchend', 'mousemove', 'mousedown',
+                    'mouseup', 'click', 'dblclick'];
+    events.forEach(type => document.addEventListener(type, record));
+  </script>
+  <style>
+    body { margin: 0; padding: 0; height: 100%; }
+    .centered {
+      position: absolute;
+      width: 40px;
+      height: 40px;
+      transform: translate(-50%,-50%);
+    }
+    #target_button { left: 50px; top: 50px; }
+    #target_iframe { left: 50px; top: 200px; }
+  </style>
+  </head>
+  <body>
+    <button id='target_button' class='centered' onclick="this.innerText='Clicked'">Button</button>
+    <iframe id='target_iframe' class='centered' src='about:blank'></iframe>
+  </body>
+</html>
diff --git a/ios/testing/http_server_bundle_data.filelist b/ios/testing/http_server_bundle_data.filelist
index b6cfda71..1cdf1b3 100644
--- a/ios/testing/http_server_bundle_data.filelist
+++ b/ios/testing/http_server_bundle_data.filelist
@@ -5,6 +5,7 @@
 #       If it requires updating, you should get a presubmit error with
 #       instructions on how to regenerate. Otherwise, do not edit.
 data/http_server_files/OWNERS
+data/http_server_files/actuation/click_tool_test.html
 data/http_server_files/article.html
 data/http_server_files/autofill_refill_test.html
 data/http_server_files/autofill_smoke_test.html
diff --git a/ios/web/js_messaging/web_frame_impl.mm b/ios/web/js_messaging/web_frame_impl.mm
index ef640ba2..177c507 100644
--- a/ios/web/js_messaging/web_frame_impl.mm
+++ b/ios/web/js_messaging/web_frame_impl.mm
@@ -186,8 +186,16 @@
                          id value,
                          NSError* error) {
   if (error) {
-    LogScriptResultError(web_state, api, script, security_origin, is_main_frame,
-                         error);
+    bool unsupportedResultError =
+        [error.domain isEqualToString:WKErrorDomain] &&
+        error.code == WKErrorJavaScriptResultTypeIsUnsupported;
+    // `JSExecutionComplete` is only called if the caller is NOT interested in
+    // the returned value from JS so we can safely ignore unsupported type
+    // errors and do not need to report them.
+    if (!unsupportedResultError) {
+      LogScriptResultError(web_state, api, script, security_origin,
+                           is_main_frame, error);
+    }
   }
 }
 
diff --git a/ios_internal b/ios_internal
index 923701b..69ec8e8 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit 923701b6eb8574642aa8d4c18b571e101fb265e5
+Subproject commit 69ec8e8ce45ad6fe43105363cddf5bec5829b322
diff --git a/media/base/android/java/src/test/org/chromium/media/CommunicationDeviceListenerTest.java b/media/base/android/java/src/test/org/chromium/media/CommunicationDeviceListenerTest.java
index 5943103..d441304 100644
--- a/media/base/android/java/src/test/org/chromium/media/CommunicationDeviceListenerTest.java
+++ b/media/base/android/java/src/test/org/chromium/media/CommunicationDeviceListenerTest.java
@@ -20,10 +20,12 @@
 import android.os.Build;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.ContextUtils;
@@ -41,9 +43,10 @@
     @Mock UsbInterface mUsbInterface;
     private CommunicationDeviceListener mListener;
 
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mListener = new CommunicationDeviceListener(mDevices);
         mListener.init(/* hasBluetoothPermission= */ true);
 
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index bcd9d1c7..5041947 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -368,6 +368,10 @@
 BASE_FEATURE(kEncryptedMediaOcclusionTracking,
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Enables extended video bitstream validation for H.264 and H.265.
+BASE_FEATURE(kExtendedVideoBitstreamValidation,
+             base::FEATURE_ENABLED_BY_DEFAULT);
+
 // Enables user control over muting tab audio from the tab strip.
 BASE_FEATURE(kEnableTabMuting, base::FEATURE_DISABLED_BY_DEFAULT);
 
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 4a7246a2..5cf1178 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -290,6 +290,10 @@
 // Enables tracking the occlusion of encrypted video elements.
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kEncryptedMediaOcclusionTracking);
 
+// Enables extended video bitstream validation for H.264 and H.265.
+// Remove after M149, once we're sure that this doesn't break anyone.
+MEDIA_EXPORT BASE_DECLARE_FEATURE(kExtendedVideoBitstreamValidation);
+
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kPlatformAudioEncoder);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kEnableRtcpReporting);
 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc
index 4894de9..39734fa5 100644
--- a/media/base/video_frame.cc
+++ b/media/base/video_frame.cc
@@ -1212,6 +1212,25 @@
   return color_space_;
 }
 
+void VideoFrame::set_color_space(const gfx::ColorSpace& color_space) {
+  // Check color spaces are same for video frames created from shared image
+  // from WrapSharedImage codepaths.
+  if (HasSharedImage() && !HasMappableSharedImage() &&
+      color_space != shared_image()->color_space()) {
+    SCOPED_CRASH_KEY_STRING256("video_frame", "si_color_space",
+                               shared_image()->color_space().ToString());
+    SCOPED_CRASH_KEY_STRING256("video_frame", "color_space",
+                               color_space.ToString());
+    SCOPED_CRASH_KEY_STRING256("video_frame", "si_label",
+                               shared_image()->debug_label());
+    DUMP_WILL_BE_CHECK(false)
+        << "VideoFrame color space (" << color_space.ToString()
+        << ") does not match SharedImage color_space ("
+        << shared_image()->color_space().ToString() << ")";
+  }
+  color_space_ = color_space;
+}
+
 gfx::ColorSpace VideoFrame::CompatRGBColorSpace() const {
   const auto rgb_color_space = ColorSpace().GetAsFullRangeRGB();
   if (!rgb_color_space.IsValid()) {
diff --git a/media/base/video_frame.h b/media/base/video_frame.h
index 1e9eef0..fa909101 100644
--- a/media/base/video_frame.h
+++ b/media/base/video_frame.h
@@ -500,9 +500,7 @@
 
   // Returns the color space of this frame's content.
   gfx::ColorSpace ColorSpace() const;
-  void set_color_space(const gfx::ColorSpace& color_space) {
-    color_space_ = color_space;
-  }
+  void set_color_space(const gfx::ColorSpace& color_space);
 
   // Return the full-range RGB component of the color space of this frame's
   // content. This will replace several color spaces (Rec601, Rec709, and
diff --git a/media/filters/vpx_video_decoder.cc b/media/filters/vpx_video_decoder.cc
index 0be38f7e..14b4044 100644
--- a/media/filters/vpx_video_decoder.cc
+++ b/media/filters/vpx_video_decoder.cc
@@ -490,11 +490,11 @@
       break;
 
     case VPX_IMG_FMT_I422:
-      codec_format = PIXEL_FORMAT_I422;
+      codec_format = vpx_image_alpha ? PIXEL_FORMAT_I422A : PIXEL_FORMAT_I422;
       break;
 
     case VPX_IMG_FMT_I444:
-      codec_format = PIXEL_FORMAT_I444;
+      codec_format = vpx_image_alpha ? PIXEL_FORMAT_I444A : PIXEL_FORMAT_I444;
       break;
 
     case VPX_IMG_FMT_I42016:
diff --git a/media/parsers/bit_reader_macros.h b/media/parsers/bit_reader_macros.h
index 3ed96c3..a49a17d 100644
--- a/media/parsers/bit_reader_macros.h
+++ b/media/parsers/bit_reader_macros.h
@@ -136,6 +136,13 @@
     }                                                                       \
   } while (0)
 
+#define IN_RANGE_IF_OR_RETURN(val, min, max, condition) \
+  do {                                                  \
+    if (condition) {                                    \
+      IN_RANGE_OR_RETURN(val, min, max);                \
+    }                                                   \
+  } while (0)
+
 #define TRUE_OR_RETURN(a)                                            \
   do {                                                               \
     if (!(a)) {                                                      \
diff --git a/media/parsers/h264_parser.cc b/media/parsers/h264_parser.cc
index 03cafeb3..a08f9046 100644
--- a/media/parsers/h264_parser.cc
+++ b/media/parsers/h264_parser.cc
@@ -14,11 +14,13 @@
 #include "base/compiler_specific.h"
 #include "base/containers/span.h"
 #include "base/containers/span_reader.h"
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/notreached.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/numerics/safe_math.h"
 #include "base/types/to_address.h"
+#include "media/base/media_switches.h"
 #include "media/base/subsample_entry.h"
 #include "media/parsers/bit_reader_macros.h"
 #include "ui/gfx/geometry/rect.h"
@@ -293,7 +295,9 @@
 static_assert(std::size(kTableSarWidth) == std::size(kTableSarHeight),
               "sar tables must have the same size");
 
-H264Parser::H264Parser() {
+H264Parser::H264Parser()
+    : validate_extended_bitstream_(
+          base::FeatureList::IsEnabled(kExtendedVideoBitstreamValidation)) {
   Reset();
 }
 
@@ -893,7 +897,9 @@
   READ_BOOL_OR_RETURN(&data);  // chroma_loc_info_present_flag
   if (data) {
     READ_UE_OR_RETURN(&data);  // chroma_sample_loc_type_top_field
+    IN_RANGE_IF_OR_RETURN(data, 0, 5, validate_extended_bitstream_);
     READ_UE_OR_RETURN(&data);  // chroma_sample_loc_type_bottom_field
+    IN_RANGE_IF_OR_RETURN(data, 0, 5, validate_extended_bitstream_);
   }
 
   // Read and ignore timing info.
@@ -925,9 +931,13 @@
   if (sps->bitstream_restriction_flag) {
     READ_BOOL_OR_RETURN(&data);  // motion_vectors_over_pic_boundaries_flag
     READ_UE_OR_RETURN(&data);    // max_bytes_per_pic_denom
+    IN_RANGE_IF_OR_RETURN(data, 0, 16, validate_extended_bitstream_);
     READ_UE_OR_RETURN(&data);    // max_bits_per_mb_denom
+    IN_RANGE_IF_OR_RETURN(data, 0, 16, validate_extended_bitstream_);
     READ_UE_OR_RETURN(&data);    // log2_max_mv_length_horizontal
+    IN_RANGE_IF_OR_RETURN(data, 0, 16, validate_extended_bitstream_);
     READ_UE_OR_RETURN(&data);    // log2_max_mv_length_vertical
+    IN_RANGE_IF_OR_RETURN(data, 0, 16, validate_extended_bitstream_);
     READ_UE_OR_RETURN(&sps->max_num_reorder_frames);
     READ_UE_OR_RETURN(&sps->max_dec_frame_buffering);
     TRUE_OR_RETURN(sps->max_dec_frame_buffering >= sps->max_num_ref_frames);
@@ -1034,6 +1044,8 @@
   }
 
   READ_UE_OR_RETURN(&sps->max_num_ref_frames);
+  IN_RANGE_IF_OR_RETURN(sps->max_num_ref_frames, 0, 16,
+                        validate_extended_bitstream_);
   READ_BOOL_OR_RETURN(&sps->gaps_in_frame_num_value_allowed_flag);
 
   READ_UE_OR_RETURN(&sps->pic_width_in_mbs_minus1);
@@ -1592,9 +1604,11 @@
     H264SEIMessage sei_msg;
     switch (type) {
       case kSEIRecoveryPoint: {
-        auto recovery_point = sei_msg.emplace<H264SEIRecoveryPoint>();
+        auto& recovery_point = sei_msg.emplace<H264SEIRecoveryPoint>();
         READ_UE_AND_MINUS_BITS_READ_OR_RETURN(
             &recovery_point.recovery_frame_cnt, &num_bits_remain);
+        IN_RANGE_IF_OR_RETURN(recovery_point.recovery_frame_cnt, 0, 65535,
+                              validate_extended_bitstream_);
         READ_BOOL_AND_MINUS_BITS_READ_OR_RETURN(
             &recovery_point.exact_match_flag, &num_bits_remain);
         READ_BOOL_AND_MINUS_BITS_READ_OR_RETURN(
diff --git a/media/parsers/h264_parser.h b/media/parsers/h264_parser.h
index 93a09d2..5da391b 100644
--- a/media/parsers/h264_parser.h
+++ b/media/parsers/h264_parser.h
@@ -620,6 +620,9 @@
   // This contains the range of the previous NALU found in
   // AdvanceToNextNalu(). Holds exactly one range.
   Ranges<const uint8_t*> previous_nalu_range_;
+
+  // Cached value of kExtendedVideoBitstreamValidation feature.
+  const bool validate_extended_bitstream_;
 };
 
 }  // namespace media
diff --git a/media/parsers/h264_parser_unittest.cc b/media/parsers/h264_parser_unittest.cc
index 0a5a9b5..a8953cf0 100644
--- a/media/parsers/h264_parser_unittest.cc
+++ b/media/parsers/h264_parser_unittest.cc
@@ -291,7 +291,7 @@
       // SEI payload size = 1.
       0x01,
       // SEI payload.
-      0x84,
+      0x7c,
       // RBSP trailing bits.
       0x80,
       // Second NALU Start code.
@@ -327,10 +327,10 @@
   for (const auto& sei_msg : recovery_point_sei.msgs) {
     const auto* recovery_point = std::get_if<H264SEIRecoveryPoint>(&sei_msg);
     ASSERT_TRUE(recovery_point);
-    EXPECT_EQ(recovery_point->recovery_frame_cnt, 0);
-    EXPECT_EQ(recovery_point->exact_match_flag, false);
-    EXPECT_EQ(recovery_point->broken_link_flag, false);
-    EXPECT_EQ(recovery_point->changing_slice_group_idc, 0);
+    EXPECT_EQ(recovery_point->recovery_frame_cnt, 2);
+    EXPECT_EQ(recovery_point->exact_match_flag, true);
+    EXPECT_EQ(recovery_point->broken_link_flag, true);
+    EXPECT_EQ(recovery_point->changing_slice_group_idc, 2);
   }
 
   ASSERT_EQ(H264Parser::kOk, parser.AdvanceToNextNALU(&target_nalu));
diff --git a/media/parsers/h265_nalu_parser.cc b/media/parsers/h265_nalu_parser.cc
index 348d041..43faa40 100644
--- a/media/parsers/h265_nalu_parser.cc
+++ b/media/parsers/h265_nalu_parser.cc
@@ -10,34 +10,20 @@
 #include <cmath>
 #include <cstring>
 
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/types/to_address.h"
 #include "media/base/decrypt_config.h"
+#include "media/base/media_switches.h"
+#include "media/parsers/bit_reader_macros.h"
 
 namespace media {
 
-#define READ_BITS_OR_RETURN(num_bits, out)                                 \
-  do {                                                                     \
-    uint32_t _out;                                                         \
-    if (!br_.ReadBits(num_bits, &_out)) {                                  \
-      DVLOG(1)                                                             \
-          << "Error in stream: unexpected EOS while trying to read " #out; \
-      return kInvalidStream;                                               \
-    }                                                                      \
-    *out = _out;                                                           \
-  } while (0)
-
-#define TRUE_OR_RETURN(a)                                            \
-  do {                                                               \
-    if (!(a)) {                                                      \
-      DVLOG(1) << "Error in stream: invalid value, expected " << #a; \
-      return kInvalidStream;                                         \
-    }                                                                \
-  } while (0)
-
 H265NALU::H265NALU() = default;
 
-H265NaluParser::H265NaluParser() {
+H265NaluParser::H265NaluParser()
+    : validate_extended_bitstream_(
+          base::FeatureList::IsEnabled(kExtendedVideoBitstreamValidation)) {
   Reset();
 }
 
@@ -145,6 +131,8 @@
 
   READ_BITS_OR_RETURN(6, &nalu->nal_unit_type);
   READ_BITS_OR_RETURN(6, &nalu->nuh_layer_id);
+  IN_RANGE_IF_OR_RETURN(nalu->nuh_layer_id, 0, 62,
+                        validate_extended_bitstream_);
   READ_BITS_OR_RETURN(3, &nalu->nuh_temporal_id_plus1);
   TRUE_OR_RETURN(nalu->nuh_temporal_id_plus1 != 0);
 
diff --git a/media/parsers/h265_nalu_parser.h b/media/parsers/h265_nalu_parser.h
index 96e7449b..5bef60a 100644
--- a/media/parsers/h265_nalu_parser.h
+++ b/media/parsers/h265_nalu_parser.h
@@ -149,6 +149,9 @@
  protected:
   H264BitReader br_;
 
+  // Cached value of kExtendedVideoBitstreamValidation feature.
+  const bool validate_extended_bitstream_;
+
  private:
   // Move the stream pointer to the beginning of the next NALU,
   // i.e. pointing at the next start code.
diff --git a/media/parsers/h265_parser.cc b/media/parsers/h265_parser.cc
index 06303f8..5ce4f01 100644
--- a/media/parsers/h265_parser.cc
+++ b/media/parsers/h265_parser.cc
@@ -543,6 +543,8 @@
       if (vps_nuh_layer_id_present_flag) {
         READ_BITS_OR_RETURN(6, &layer_id_in_nuh_i);
       }
+      IN_RANGE_IF_OR_RETURN(layer_id_in_nuh_i, 0, 62,
+                            validate_extended_bitstream_);
       std::array<int, 16> dimension_id_i = {};
       if (!splitting_flag) {
         for (int j = 0; j < num_scalability_types; ++j) {
@@ -1878,7 +1880,9 @@
   READ_BOOL_OR_RETURN(&data);  // chroma_loc_info_present_flag
   if (data) {
     READ_UE_OR_RETURN(&data);  // chroma_sample_loc_type_top_field
+    IN_RANGE_IF_OR_RETURN(data, 0, 5, validate_extended_bitstream_);
     READ_UE_OR_RETURN(&data);  // chroma_sample_loc_type_bottom_field
+    IN_RANGE_IF_OR_RETURN(data, 0, 5, validate_extended_bitstream_);
   }
 
   // Ignore neutral_chroma_indication_flag, field_seq_flag and
@@ -1913,10 +1917,20 @@
     // and restricted_ref_pic_lists_flag.
     SKIP_BITS_OR_RETURN(3);
     READ_UE_OR_RETURN(&vui->min_spatial_segmentation_idc);
+    IN_RANGE_IF_OR_RETURN(vui->min_spatial_segmentation_idc, 0, 4095,
+                          validate_extended_bitstream_);
     READ_UE_OR_RETURN(&vui->max_bytes_per_pic_denom);
+    IN_RANGE_IF_OR_RETURN(vui->max_bytes_per_pic_denom, 0, 16,
+                          validate_extended_bitstream_);
     READ_UE_OR_RETURN(&vui->max_bits_per_min_cu_denom);
+    IN_RANGE_IF_OR_RETURN(vui->max_bits_per_min_cu_denom, 0, 16,
+                          validate_extended_bitstream_);
     READ_UE_OR_RETURN(&vui->log2_max_mv_length_horizontal);
+    IN_RANGE_IF_OR_RETURN(vui->log2_max_mv_length_horizontal, 0, 16,
+                          validate_extended_bitstream_);
     READ_UE_OR_RETURN(&vui->log2_max_mv_length_vertical);
+    IN_RANGE_IF_OR_RETURN(vui->log2_max_mv_length_vertical, 0, 16,
+                          validate_extended_bitstream_);
   }
 
   return kOk;
@@ -2193,6 +2207,8 @@
           IN_RANGE_OR_RETURN(info.alpha_channel_use_idc, 0, 2);
           READ_BITS_AND_MINUS_BITS_READ_OR_RETURN(
               3, &info.alpha_channel_bit_depth_minus8, &num_bits_remain);
+          IN_RANGE_IF_OR_RETURN(info.alpha_channel_bit_depth_minus8, 0, 7,
+                                validate_extended_bitstream_);
           READ_BITS_AND_MINUS_BITS_READ_OR_RETURN(
               info.alpha_channel_bit_depth_minus8 + 9,
               &info.alpha_transparent_value, &num_bits_remain);
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc
index e91ba28..a5330a7 100644
--- a/media/renderers/video_resource_updater.cc
+++ b/media/renderers/video_resource_updater.cc
@@ -270,6 +270,12 @@
       return viz::MultiPlaneFormat::kNV12A;
     case PIXEL_FORMAT_I420A:
       return viz::MultiPlaneFormat::kI420A;
+    case PIXEL_FORMAT_I422A:
+      return viz::SharedImageFormat::MultiPlane(
+          PlaneConfig::kY_U_V_A, Subsampling::k422, ChannelFormat::k8);
+    case PIXEL_FORMAT_I444A:
+      return viz::SharedImageFormat::MultiPlane(
+          PlaneConfig::kY_U_V_A, Subsampling::k444, ChannelFormat::k8);
     case PIXEL_FORMAT_NV16:
     case PIXEL_FORMAT_NV24:
     case PIXEL_FORMAT_P010LE:
@@ -289,8 +295,6 @@
     case PIXEL_FORMAT_XB30:
     case PIXEL_FORMAT_BGRA:
     case PIXEL_FORMAT_RGBAF16:
-    case PIXEL_FORMAT_I422A:
-    case PIXEL_FORMAT_I444A:
     case PIXEL_FORMAT_YUV420AP10:
     case PIXEL_FORMAT_YUV422AP10:
     case PIXEL_FORMAT_YUV444AP10:
diff --git a/media/test/data/README.md b/media/test/data/README.md
index c78db76f..e432aa9 100644
--- a/media/test/data/README.md
+++ b/media/test/data/README.md
@@ -25,6 +25,18 @@
 #### bear-vp9.webm
 VP9 video only WebM file.
 
+#### bear-vp9a-422.webm
+VP9 video with alpha channel and yuv 422 subsampling.
+```
+ffmpeg -c:v libvpx-vp9 -i bear-vp9a.webm -pix_fmt yuva422p -strict experimental bear-vp9a-422.webm
+```
+
+#### bear-vp9a-444.webm
+VP9 video with alpha channel and yuv 444 subsampling.
+```
+ffmpeg -c:v libvpx-vp9 -i bear-vp9a.webm -pix_fmt yuva444p -strict experimental bear-vp9a-444.webm
+```
+
 #### bear-vp9-opus.webm
 VP9 Video with Opus Audio.
 
diff --git a/media/test/data/bear-vp9a-422.webm b/media/test/data/bear-vp9a-422.webm
new file mode 100644
index 0000000..8cf69ee
--- /dev/null
+++ b/media/test/data/bear-vp9a-422.webm
Binary files differ
diff --git a/media/test/data/bear-vp9a-444.webm b/media/test/data/bear-vp9a-444.webm
new file mode 100644
index 0000000..b931c1f3
--- /dev/null
+++ b/media/test/data/bear-vp9a-444.webm
Binary files differ
diff --git a/media/test/media_bundle_data.filelist b/media/test/media_bundle_data.filelist
index 9dc5c75..e2e7fd4 100644
--- a/media/test/media_bundle_data.filelist
+++ b/media/test/media_bundle_data.filelist
@@ -225,6 +225,8 @@
 data/bear-vp9.ivf
 data/bear-vp9.ivf.context
 data/bear-vp9.webm
+data/bear-vp9a-422.webm
+data/bear-vp9a-444.webm
 data/bear-vp9a-odd-dimensions.webm
 data/bear-vp9a.webm
 data/bear.ac3
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc
index 70ec9887..1c357a1 100644
--- a/media/test/pipeline_integration_test.cc
+++ b/media/test/pipeline_integration_test.cc
@@ -2847,6 +2847,22 @@
   EXPECT_EQ(last_video_frame_format_, PIXEL_FORMAT_I420A);
 }
 
+// Verify that VP9 422 video with alpha channel can be played back.
+TEST_F(PipelineIntegrationTest, BasicPlayback_VP9A_422_WebM) {
+  ASSERT_EQ(PIPELINE_OK, Start("bear-vp9a-422.webm"));
+  Play();
+  ASSERT_TRUE(WaitUntilOnEnded());
+  EXPECT_EQ(last_video_frame_format_, PIXEL_FORMAT_I422A);
+}
+
+// Verify that VP9 444 video with alpha channel can be played back.
+TEST_F(PipelineIntegrationTest, BasicPlayback_VP9A_444_WebM) {
+  ASSERT_EQ(PIPELINE_OK, Start("bear-vp9a-444.webm"));
+  Play();
+  ASSERT_TRUE(WaitUntilOnEnded());
+  EXPECT_EQ(last_video_frame_format_, PIXEL_FORMAT_I444A);
+}
+
 // Verify that VP9 video with 4:4:4 subsampling can be played back.
 TEST_F(PipelineIntegrationTest, P444_VP9_WebM) {
   ASSERT_EQ(PIPELINE_OK, Start("bear-320x240-P444.webm"));
diff --git a/media/unit_tests_bundle_data.filelist b/media/unit_tests_bundle_data.filelist
index af6baae..6d5ed9c2 100644
--- a/media/unit_tests_bundle_data.filelist
+++ b/media/unit_tests_bundle_data.filelist
@@ -237,6 +237,8 @@
 //media/test/data/bear-vp9.ivf
 //media/test/data/bear-vp9.ivf.context
 //media/test/data/bear-vp9.webm
+//media/test/data/bear-vp9a-422.webm
+//media/test/data/bear-vp9a-444.webm
 //media/test/data/bear-vp9a-odd-dimensions.webm
 //media/test/data/bear-vp9a.webm
 //media/test/data/bear.ac3
diff --git a/mojo/public/cpp/base/big_string_mojom_traits.cc b/mojo/public/cpp/base/big_string_mojom_traits.cc
index f6180f7c..ed0b0586 100644
--- a/mojo/public/cpp/base/big_string_mojom_traits.cc
+++ b/mojo/public/cpp/base/big_string_mojom_traits.cc
@@ -4,7 +4,7 @@
 
 #include "mojo/public/cpp/base/big_string_mojom_traits.h"
 
-#include "base/compiler_specific.h"
+#include "base/containers/span.h"
 #include "mojo/public/cpp/base/big_buffer_mojom_traits.h"
 
 namespace mojo {
@@ -12,8 +12,7 @@
 // static
 mojo_base::BigBuffer StructTraits<mojo_base::mojom::BigStringDataView,
                                   std::string>::data(const std::string& str) {
-  const auto* bytes = reinterpret_cast<const uint8_t*>(str.data());
-  return mojo_base::BigBuffer(UNSAFE_TODO(base::span(bytes, str.size())));
+  return mojo_base::BigBuffer(base::as_byte_span(str));
 }
 
 // static
diff --git a/mojo/public/cpp/base/proto_wrapper.cc b/mojo/public/cpp/base/proto_wrapper.cc
index 4cd9f2f..a1df258 100644
--- a/mojo/public/cpp/base/proto_wrapper.cc
+++ b/mojo/public/cpp/base/proto_wrapper.cc
@@ -7,7 +7,6 @@
 #include <limits>
 
 #include "base/check_op.h"
-#include "base/compiler_specific.h"
 #include "third_party/protobuf/src/google/protobuf/message_lite.h"
 
 namespace mojo_base {
@@ -57,8 +56,7 @@
   } else {
     // Make an in-process copy here as protobuf is not designed to
     // safely parse data that might be changing underneath it.
-    auto as_span = UNSAFE_TODO(base::span(bytes_->data(), bytes_->size()));
-    const std::vector<uint8_t> copy(as_span.begin(), as_span.end());
+    const std::vector<uint8_t> copy(std::from_range, *bytes_);
     return message.ParseFromArray(copy.data(), copy.size());
   }
 }
diff --git a/mojo/public/cpp/base/string16_mojom_traits.cc b/mojo/public/cpp/base/string16_mojom_traits.cc
index e9fd72f..3ab355e 100644
--- a/mojo/public/cpp/base/string16_mojom_traits.cc
+++ b/mojo/public/cpp/base/string16_mojom_traits.cc
@@ -4,7 +4,7 @@
 
 #include "mojo/public/cpp/base/string16_mojom_traits.h"
 
-#include "base/compiler_specific.h"
+#include "base/containers/span.h"
 #include "mojo/public/cpp/base/big_buffer_mojom_traits.h"
 
 namespace mojo {
@@ -23,9 +23,7 @@
 mojo_base::BigBuffer
 StructTraits<mojo_base::mojom::BigString16DataView, std::u16string>::data(
     const std::u16string& str) {
-  const auto* bytes = reinterpret_cast<const uint8_t*>(str.data());
-  return mojo_base::BigBuffer(
-      UNSAFE_TODO(base::span(bytes, str.size() * sizeof(char16_t))));
+  return mojo_base::BigBuffer(base::as_byte_span(str));
 }
 
 // static
diff --git a/mojo/public/cpp/base/values_mojom_traits.cc b/mojo/public/cpp/base/values_mojom_traits.cc
index 30552a66..3926957 100644
--- a/mojo/public/cpp/base/values_mojom_traits.cc
+++ b/mojo/public/cpp/base/values_mojom_traits.cc
@@ -7,7 +7,6 @@
 #include <memory>
 #include <utility>
 
-#include "base/compiler_specific.h"
 #include "base/features.h"
 
 namespace mojo {
@@ -87,10 +86,7 @@
     case mojo_base::mojom::ValueDataView::Tag::kBinaryValue: {
       mojo::ArrayDataView<uint8_t> binary_data_view;
       data.GetBinaryValueDataView(&binary_data_view);
-      const char* data_pointer =
-          reinterpret_cast<const char*>(binary_data_view.data());
-      base::Value::BlobStorage blob_storage(
-          data_pointer, UNSAFE_TODO(data_pointer + binary_data_view.size()));
+      base::Value::BlobStorage blob_storage(std::from_range, binary_data_view);
       *value_out = base::Value(std::move(blob_storage));
       return true;
     }
diff --git a/mojo/public/cpp/bindings/tests/message_unittest.cc b/mojo/public/cpp/bindings/tests/message_unittest.cc
index 0d505d8a..9f5b669 100644
--- a/mojo/public/cpp/bindings/tests/message_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/message_unittest.cc
@@ -32,9 +32,7 @@
   }
 
   bytes->resize(message.data_num_bytes());
-  std::copy(message.data(),
-            UNSAFE_TODO(message.data() + message.data_num_bytes()),
-            bytes->begin());
+  std::ranges::copy(message.data_as_span(), bytes->begin());
 
   MessagePipe pipe;
   handles->resize(2);
diff --git a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
index f652c3b..63186ca 100644
--- a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
@@ -11,7 +11,7 @@
 #include <string>
 #include <utility>
 
-#include "base/compiler_specific.h"
+#include "base/containers/span.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
@@ -237,10 +237,10 @@
   }
 }
 
-void DumpHex(const uint8_t* bytes, size_t num_bytes) {
-  for (size_t i = 0; i < num_bytes; ++i) {
+void DumpHex(base::span<const uint8_t> bytes) {
+  for (size_t i = 0; i < bytes.size(); ++i) {
     std::cout << std::setw(2) << std::setfill('0') << std::hex
-              << uint32_t(UNSAFE_TODO(bytes[i]));
+              << static_cast<uint32_t>(bytes[i]);
 
     if (i % 16 == 15) {
       std::cout << std::endl;
@@ -300,8 +300,7 @@
     // Imagine some IPC happened here.
 
     if (g_dump_message_as_hex) {
-      DumpHex(reinterpret_cast<const uint8_t*>(message->data()),
-              message->data_num_bytes());
+      DumpHex(message->data_as_span());
     }
 
     // In the receiving process, an implementation of ServiceStub is known to
diff --git a/mojo/public/cpp/bindings/tests/validation_unittest.cc b/mojo/public/cpp/bindings/tests/validation_unittest.cc
index 0f81c33..7784f5c3 100644
--- a/mojo/public/cpp/bindings/tests/validation_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/validation_unittest.cc
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
+#include "base/containers/span.h"
 #include "base/memory/raw_ptr.h"
 #include "base/numerics/safe_math.h"
 #include "base/run_loop.h"
@@ -59,10 +60,14 @@
 }
 
 template <typename T>
-void Append(std::vector<uint8_t>* data_vector, T data) {
-  size_t pos = data_vector->size();
-  data_vector->resize(pos + sizeof(T));
-  UNSAFE_TODO(memcpy(&(*data_vector)[pos], &data, sizeof(T)));
+void Append(std::vector<uint8_t>* data_vector, const T data) {
+  base::span<const uint8_t> bytes;
+  if constexpr (std::is_same_v<T, double> || std::is_same_v<T, float>) {
+    bytes = base::byte_span_from_ref(base::allow_nonunique_obj, data);
+  } else {
+    bytes = base::byte_span_from_ref(data);
+  }
+  data_vector->append_range(bytes);
 }
 
 bool TestInputParser(const std::string& input,
diff --git a/mojo/public/cpp/platform/tests/platform_channel_server_unittest.cc b/mojo/public/cpp/platform/tests/platform_channel_server_unittest.cc
index 93a7fbee..31fe6ab 100644
--- a/mojo/public/cpp/platform/tests/platform_channel_server_unittest.cc
+++ b/mojo/public/cpp/platform/tests/platform_channel_server_unittest.cc
@@ -8,7 +8,6 @@
 #include <tuple>
 #include <utility>
 
-#include "base/compiler_specific.h"
 #include "base/containers/span.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/callback.h"
@@ -68,9 +67,7 @@
   }
 
   void SendMessage(const std::string& message) {
-    auto data = UNSAFE_TODO(base::span(
-        reinterpret_cast<const uint8_t*>(message.data()), message.size()));
-    channel_->WriteNextIpczMessage(data, {});
+    channel_->WriteNextIpczMessage(base::as_byte_span(message), {});
   }
 
   std::string WaitForSingleMessage() {
diff --git a/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc b/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc
index 56ee55f..6f341be 100644
--- a/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc
+++ b/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc
@@ -58,10 +58,9 @@
       return false;
     }
 
-    size_t size = message->data_num_bytes();
-    const uint8_t* data = message->data();
-    if (!file.WriteAtCurrentPosAndCheck(UNSAFE_TODO(base::span(data, size)))) {
-      LOG(ERROR) << "Failed to write " << size << " bytes.";
+    if (!file.WriteAtCurrentPosAndCheck(message->data_as_span())) {
+      LOG(ERROR) << "Failed to write " << message->data_num_bytes()
+                 << " bytes.";
       return false;
     }
     return true;
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 60f83cc..259cdd4 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -4354,6 +4354,7 @@
   fuzzer_test("net_url_conversions_fuzzer") {
     sources = [ "base/apple/url_conversions_fuzzer.mm" ]
     deps = [
+      ":net_fuzzer_test_support",
       "//base",
       "//net",
     ]
diff --git a/net/android/junit/src/org/chromium/net/HttpNegotiateAuthenticatorTest.java b/net/android/junit/src/org/chromium/net/HttpNegotiateAuthenticatorTest.java
index 41a2973..02925ea 100644
--- a/net/android/junit/src/org/chromium/net/HttpNegotiateAuthenticatorTest.java
+++ b/net/android/junit/src/org/chromium/net/HttpNegotiateAuthenticatorTest.java
@@ -33,12 +33,14 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
@@ -82,9 +84,10 @@
     @Captor private ArgumentCaptor<AccountManagerCallback<Account[]>> mAccountCallbackCaptor;
     @Captor private ArgumentCaptor<Bundle> mBundleCaptor;
 
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         HttpNegotiateAuthenticatorJni.setInstanceForTesting(mAuthenticatorJniMock);
     }
 
diff --git a/net/device_bound_sessions/session_service_impl.cc b/net/device_bound_sessions/session_service_impl.cc
index 8f7fa67..5c88860 100644
--- a/net/device_bound_sessions/session_service_impl.cc
+++ b/net/device_bound_sessions/session_service_impl.cc
@@ -628,15 +628,7 @@
   it->second.emplace_back(std::move(callback));
 
   auto* session = GetSession(session_key);
-  CHECK(session, base::NotFatalUntil::M147);
-  // TODO(crbug.com/417770933): Remove this block.
-  if (!session) {
-    // If we can't find the session, clear the `session_key` in the map
-    // and continue all related requests. We can call this a fatal error
-    // because the session has already been deleted.
-    UnblockDeferredRequests(session_key, RefreshResult::kFatalError);
-    return;
-  }
+  CHECK(session);
   // Notify the request that it has been deferred for refreshed cookies.
   NotifySessionAccess(request.device_bound_session_access_callback(),
                       SessionAccess::AccessType::kUpdate, session_key,
diff --git a/net/dns/public/doh_provider_entry.cc b/net/dns/public/doh_provider_entry.cc
index f1f9ab1..386c76b 100644
--- a/net/dns/public/doh_provider_entry.cc
+++ b/net/dns/public/doh_provider_entry.cc
@@ -71,110 +71,127 @@
   //
   // LINT.IfChange(DohProviderId)
   static const auto entries(base::NoDestructor(std::to_array<DohProviderEntry>(
-      {{"CleanBrowsingAdult",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderCleanBrowsingAdult,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"185.228.168.10", "185.228.169.11", "2a0d:2a00:1::1",
-         "2a0d:2a00:2::1"},
-        /*dns_over_tls_hostnames=*/{"adult-filter-dns.cleanbrowsing.org"},
-        "https://doh.cleanbrowsing.org/doh/adult-filter{?dns}",
-        /*ui_name=*/"",
-        /*privacy_policy=*/"",
-        /*display_globally=*/false,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal},
-       {"CleanBrowsingFamily",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderCleanBrowsingFamily,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"185.228.168.168", "185.228.169.168",
-         "2a0d:2a00:1::", "2a0d:2a00:2::"},
-        /*dns_over_tls_hostnames=*/{"family-filter-dns.cleanbrowsing.org"},
-        "https://doh.cleanbrowsing.org/doh/family-filter{?dns}",
-        /*ui_name=*/"CleanBrowsing (Family Filter)",
-        /*privacy_policy=*/"https://cleanbrowsing.org/privacy",
-        /*display_globally=*/true,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal},
-       {"CleanBrowsingSecure",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderCleanBrowsingSecure,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"185.228.168.9", "185.228.169.9", "2a0d:2a00:1::2", "2a0d:2a00:2::2"},
-        /*dns_over_tls_hostnames=*/{"security-filter-dns.cleanbrowsing.org"},
-        "https://doh.cleanbrowsing.org/doh/security-filter{?dns}",
-        /*ui_name=*/"",
-        /*privacy_policy=*/"",
-        /*display_globally=*/false,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal},
-       {"Cloudflare",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderCloudflare,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001"},
-        /*dns_over_tls_hostnames=*/
-        {"one.one.one.one", "1dot1dot1dot1.cloudflare-dns.com"},
-        "https://chrome.cloudflare-dns.com/dns-query",
-        /*ui_name=*/"Cloudflare (1.1.1.1)",
-        "https://developers.cloudflare.com/1.1.1.1/privacy/"
-        /*privacy_policy=*/"public-dns-resolver/",
-        /*display_globally=*/true,
-        /*display_countries=*/{},
-        LoggingLevel::kExtra},
-       {"CloudflareFamily",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
-            DohProviderCloudflareFamily, base::FEATURE_DISABLED_BY_DEFAULT),
-        {"1.1.1.3", "1.0.0.3", "2606:4700:4700::1113", "2606:4700:4700::1003"},
-        {"family.cloudflare-dns.com"},
-        "https://family.cloudflare-dns.com/dns-query",
-        /*ui_name=*/"",
-        /*privacy_policy=*/"",
-        /*display_globally=*/false,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal},
-       {"CloudflareSecurity",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
-            DohProviderCloudflareSecurity, base::FEATURE_DISABLED_BY_DEFAULT),
-        {"1.1.1.2", "1.0.0.2", "2606:4700:4700::1112", "2606:4700:4700::1002"},
-        {"security.cloudflare-dns.com"},
-        "https://security.cloudflare-dns.com/dns-query",
-        /*ui_name=*/"",
-        /*privacy_policy=*/"",
-        /*display_globally=*/false,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal},
-       {"Comcast",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderComcast,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"75.75.75.75", "75.75.76.76", "2001:558:feed::1", "2001:558:feed::2"},
-        /*dns_over_tls_hostnames=*/{"dot.xfinity.com"},
-        "https://doh.xfinity.com/dns-query{?dns}",
-        /*ui_name=*/"",
-        /*privacy_policy*/ "",
-        /*display_globally=*/false,
-        /*display_countries=*/{},
-        LoggingLevel::kExtra},
-       {"Cox",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderCox,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"68.105.28.11", "68.105.28.12", "2001:578:3f::30"},
-        /*dns_over_tls_hostnames=*/{"dot.cox.net"},
-        "https://doh.cox.net/dns-query",
-        /*ui_name=*/"",
-        /*privacy_policy=*/"",
-        /*display_globally=*/false,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal},
-       {"Cznic",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderCznic,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"185.43.135.1", "193.17.47.1", "2001:148f:fffe::1",
-         "2001:148f:ffff::1"},
-        /*dns_over_tls_hostnames=*/{"odvr.nic.cz"},
-        "https://odvr.nic.cz/doh",
-        /*ui_name=*/"CZ.NIC ODVR",
-        /*privacy_policy=*/"https://www.nic.cz/odvr/",
-        /*display_globally=*/false,
-        /*display_countries=*/{"CZ"},
-        LoggingLevel::kNormal},
+      {{
+           "CleanBrowsingAdult",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderCleanBrowsingAdult, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"185.228.168.10", "185.228.169.11", "2a0d:2a00:1::1",
+            "2a0d:2a00:2::1"},
+           /*dns_over_tls_hostnames=*/{"adult-filter-dns.cleanbrowsing.org"},
+           "https://doh.cleanbrowsing.org/doh/adult-filter{?dns}",
+           /*ui_name=*/"",
+           /*privacy_policy=*/"",
+           /*display_globally=*/false,
+           /*display_countries=*/{},
+       },
+       {
+           "CleanBrowsingFamily",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderCleanBrowsingFamily,
+               base::FEATURE_ENABLED_BY_DEFAULT),
+           {"185.228.168.168", "185.228.169.168",
+            "2a0d:2a00:1::", "2a0d:2a00:2::"},
+           /*dns_over_tls_hostnames=*/{"family-filter-dns.cleanbrowsing.org"},
+           "https://doh.cleanbrowsing.org/doh/family-filter{?dns}",
+           /*ui_name=*/"CleanBrowsing (Family Filter)",
+           /*privacy_policy=*/"https://cleanbrowsing.org/privacy",
+           /*display_globally=*/true,
+           /*display_countries=*/{},
+       },
+       {
+           "CleanBrowsingSecure",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderCleanBrowsingSecure,
+               base::FEATURE_ENABLED_BY_DEFAULT),
+           {"185.228.168.9", "185.228.169.9", "2a0d:2a00:1::2",
+            "2a0d:2a00:2::2"},
+           /*dns_over_tls_hostnames=*/{"security-filter-dns.cleanbrowsing.org"},
+           "https://doh.cleanbrowsing.org/doh/security-filter{?dns}",
+           /*ui_name=*/"",
+           /*privacy_policy=*/"",
+           /*display_globally=*/false,
+           /*display_countries=*/{},
+       },
+       {
+           "Cloudflare",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderCloudflare, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"1.1.1.1", "1.0.0.1", "2606:4700:4700::1111",
+            "2606:4700:4700::1001"},
+           /*dns_over_tls_hostnames=*/
+           {"one.one.one.one", "1dot1dot1dot1.cloudflare-dns.com"},
+           "https://chrome.cloudflare-dns.com/dns-query",
+           /*ui_name=*/"Cloudflare (1.1.1.1)",
+           "https://developers.cloudflare.com/1.1.1.1/privacy/"
+           /*privacy_policy=*/"public-dns-resolver/",
+           /*display_globally=*/true,
+           /*display_countries=*/{},
+       },
+       {
+           "CloudflareFamily",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderCloudflareFamily, base::FEATURE_DISABLED_BY_DEFAULT),
+           {"1.1.1.3", "1.0.0.3", "2606:4700:4700::1113",
+            "2606:4700:4700::1003"},
+           {"family.cloudflare-dns.com"},
+           "https://family.cloudflare-dns.com/dns-query",
+           /*ui_name=*/"",
+           /*privacy_policy=*/"",
+           /*display_globally=*/false,
+           /*display_countries=*/{},
+       },
+       {
+           "CloudflareSecurity",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderCloudflareSecurity,
+               base::FEATURE_DISABLED_BY_DEFAULT),
+           {"1.1.1.2", "1.0.0.2", "2606:4700:4700::1112",
+            "2606:4700:4700::1002"},
+           {"security.cloudflare-dns.com"},
+           "https://security.cloudflare-dns.com/dns-query",
+           /*ui_name=*/"",
+           /*privacy_policy=*/"",
+           /*display_globally=*/false,
+           /*display_countries=*/{},
+       },
+       {
+           "Comcast",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderComcast, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"75.75.75.75", "75.75.76.76", "2001:558:feed::1",
+            "2001:558:feed::2"},
+           /*dns_over_tls_hostnames=*/{"dot.xfinity.com"},
+           "https://doh.xfinity.com/dns-query{?dns}",
+           /*ui_name=*/"",
+           /*privacy_policy*/ "",
+           /*display_globally=*/false,
+           /*display_countries=*/{},
+       },
+       {
+           "Cox",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderCox, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"68.105.28.11", "68.105.28.12", "2001:578:3f::30"},
+           /*dns_over_tls_hostnames=*/{"dot.cox.net"},
+           "https://doh.cox.net/dns-query",
+           /*ui_name=*/"",
+           /*privacy_policy=*/"",
+           /*display_globally=*/false,
+           /*display_countries=*/{},
+       },
+       {
+           "Cznic",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderCznic, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"185.43.135.1", "193.17.47.1", "2001:148f:fffe::1",
+            "2001:148f:ffff::1"},
+           /*dns_over_tls_hostnames=*/{"odvr.nic.cz"},
+           "https://odvr.nic.cz/doh",
+           /*ui_name=*/"CZ.NIC ODVR",
+           /*privacy_policy=*/"https://www.nic.cz/odvr/",
+           /*display_globally=*/false,
+           /*display_countries=*/{"CZ"},
+       },
        {"DNS4EU",
         MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderDns4eu,
                                               base::FEATURE_ENABLED_BY_DEFAULT),
@@ -190,54 +207,60 @@
                                "EE", "FI", "FR", "DE", "GR", "HU", "IE",
                                "IT", "LV", "LT", "LU", "MT", "NL", "PL",
                                "PT", "RO", "SK", "SI", "ES", "SE"},
-        LoggingLevel::kNormal,
         /*dns_over_https_server_ip_strs=*/
         {"86.54.11.1", "86.54.11.201", "2a13:1001::86:54:11:1",
          "2a13:1001::86:54:11:201"}},
-       {"Dnssb",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderDnssb,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"185.222.222.222", "45.11.45.11", "2a09::", "2a11::"},
-        /*dns_over_tls_hostnames=*/{"dns.sb"},
-        "https://doh.dns.sb/dns-query{?dns}",
-        /*ui_name=*/"DNS.SB",
-        /*privacy_policy=*/"https://dns.sb/privacy/",
-        /*display_globally=*/false,
-        /*display_countries=*/{"EE", "DE"},
-        LoggingLevel::kNormal},
-       {"Google",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderGoogle,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"8.8.8.8", "8.8.4.4", "2001:4860:4860::8888", "2001:4860:4860::8844"},
-        /*dns_over_tls_hostnames=*/
-        {"dns.google", "dns.google.com", "8888.google"},
-        "https://dns.google/dns-query{?dns}",
-        /*ui_name=*/"Google (Public DNS)",
-        "https://developers.google.com/speed/public-dns/"
-        /*privacy_policy=*/"privacy",
-        /*display_globally=*/true,
-        /*display_countries=*/{},
-        LoggingLevel::kExtra},
-       {"GoogleDns64",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderGoogleDns64,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"2001:4860:4860::64", "2001:4860:4860::6464"},
-        /*dns_over_tls_hostnames=*/{"dns64.dns.google"},
-        "https://dns64.dns.google/dns-query{?dns}",
-        /*ui_name=*/"",
-        /*privacy_policy=*/"",
-        /*display_globally=*/false,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal},
-       {"Iij",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderIij,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        /*dns_over_53_server_ip_strs=*/{},
-        /*dns_over_tls_hostnames=*/{}, "https://public.dns.iij.jp/dns-query",
-        /*ui_name=*/"IIJ (Public DNS)",
-        /*privacy_policy=*/"https://policy.public.dns.iij.jp/",
-        /*display_globally=*/false, /*display_countries=*/{"JP"},
-        LoggingLevel::kNormal},
+       {
+           "Dnssb",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderDnssb, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"185.222.222.222", "45.11.45.11", "2a09::", "2a11::"},
+           /*dns_over_tls_hostnames=*/{"dns.sb"},
+           "https://doh.dns.sb/dns-query{?dns}",
+           /*ui_name=*/"DNS.SB",
+           /*privacy_policy=*/"https://dns.sb/privacy/",
+           /*display_globally=*/false,
+           /*display_countries=*/{"EE", "DE"},
+       },
+       {
+           "Google",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderGoogle, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"8.8.8.8", "8.8.4.4", "2001:4860:4860::8888",
+            "2001:4860:4860::8844"},
+           /*dns_over_tls_hostnames=*/
+           {"dns.google", "dns.google.com", "8888.google"},
+           "https://dns.google/dns-query{?dns}",
+           /*ui_name=*/"Google (Public DNS)",
+           "https://developers.google.com/speed/public-dns/"
+           /*privacy_policy=*/"privacy",
+           /*display_globally=*/true,
+           /*display_countries=*/{},
+       },
+       {
+           "GoogleDns64",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderGoogleDns64, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"2001:4860:4860::64", "2001:4860:4860::6464"},
+           /*dns_over_tls_hostnames=*/{"dns64.dns.google"},
+           "https://dns64.dns.google/dns-query{?dns}",
+           /*ui_name=*/"",
+           /*privacy_policy=*/"",
+           /*display_globally=*/false,
+           /*display_countries=*/{},
+       },
+       {
+           "Iij",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderIij, base::FEATURE_ENABLED_BY_DEFAULT),
+           /*dns_over_53_server_ip_strs=*/{},
+           /*dns_over_tls_hostnames=*/{},
+           "https://public.dns.iij.jp/dns-query",
+           /*ui_name=*/"IIJ (Public DNS)",
+           /*privacy_policy=*/"https://policy.public.dns.iij.jp/",
+           /*display_globally=*/false,
+           /*display_countries=*/{"JP"},
+       },
        {"Levonet",
         MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderLevonet,
                                               base::FEATURE_ENABLED_BY_DEFAULT),
@@ -249,112 +272,122 @@
         /*privacy_policy=*/"",
         /*display_globally=*/false,
         /*display_countries=*/{},
-        LoggingLevel::kNormal,
         {"109.236.119.2", "109.236.120.2", "2a02:6ca3:0:1::2",
          "2a02:6ca3:0:2::2"}},
-       {"NextDns",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderNextDns,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        /*dns_over_53_server_ip_strs=*/{},
-        /*dns_over_tls_hostnames=*/{}, "https://chromium.dns.nextdns.io",
-        /*ui_name=*/"NextDNS",
-        /*privacy_policy=*/"https://nextdns.io/privacy",
-        /*display_globally=*/false, /*display_countries=*/{"US"},
-        LoggingLevel::kNormal},
-       {"OpenDNS",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderOpenDNS,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"208.67.222.222", "208.67.220.220", "2620:119:35::35",
-         "2620:119:53::53"},
-        /*dns_over_tls_hostnames=*/{},
-        "https://doh.opendns.com/dns-query{?dns}",
-        /*ui_name=*/"OpenDNS",
-        "https://www.cisco.com/c/en/us/about/legal/"
-        /*privacy_policy=*/"privacy-full.html",
-        /*display_globally=*/true,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal},
-       {"OpenDNSFamily",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderOpenDNSFamily,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"208.67.222.123", "208.67.220.123", "2620:119:35::123",
-         "2620:119:53::123"},
-        /*dns_over_tls_hostnames=*/{},
-        "https://doh.familyshield.opendns.com/dns-query{?dns}",
-        /*ui_name=*/"",
-        /*privacy_policy=*/"",
-        /*display_globally=*/false,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal},
-       {"Quad9Cdn",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderQuad9Cdn,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"9.9.9.11", "149.112.112.11", "2620:fe::11", "2620:fe::fe:11"},
-        /*dns_over_tls_hostnames=*/{"dns11.quad9.net"},
-        "https://dns11.quad9.net/dns-query",
-        /*ui_name=*/"",
-        /*privacy_policy=*/"",
-        /*display_globally=*/false,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal},
-       {"Quad9Insecure",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderQuad9Insecure,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"9.9.9.10", "149.112.112.10", "2620:fe::10", "2620:fe::fe:10"},
-        /*dns_over_tls_hostnames=*/{"dns10.quad9.net"},
-        "https://dns10.quad9.net/dns-query",
-        /*ui_name=*/"",
-        /*privacy_policy=*/"",
-        /*display_globally=*/false,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal},
-       {"Quad9Secure",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
-            DohProviderQuad9Secure, base::FEATURE_DISABLED_BY_DEFAULT),
-        {"9.9.9.9", "149.112.112.112", "2620:fe::fe", "2620:fe::9"},
-        /*dns_over_tls_hostnames=*/{"dns.quad9.net", "dns9.quad9.net"},
-        "https://dns.quad9.net/dns-query",
-        /*ui_name=*/"Quad9 (9.9.9.9)",
-        /*privacy_policy=*/"https://www.quad9.net/home/privacy/",
-        /*display_globally=*/true,
-        /*display_countries=*/{},
-        LoggingLevel::kExtra},
-       {"Quickline",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderQuickline,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"212.60.61.246", "212.60.63.246", "2001:1a88:10:ffff::1",
-         "2001:1a88:10:ffff::2"},
-        /*dns_over_tls_hostnames=*/{"dot.quickline.ch"},
-        "https://doh.quickline.ch/dns-query{?dns}",
-        /*ui_name=*/"",
-        /*privacy_policy=*/"",
-        /*display_globally=*/false,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal},
-       {"Spectrum1",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderSpectrum1,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"209.18.47.61", "209.18.47.62", "2001:1998:0f00:0001::1",
-         "2001:1998:0f00:0002::1"},
-        /*dns_over_tls_hostnames=*/{},
-        "https://doh-01.spectrum.com/dns-query{?dns}",
-        /*ui_name=*/"",
-        /*privacy_policy=*/"",
-        /*display_globally=*/false,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal},
-       {"Spectrum2",
-        MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(DohProviderSpectrum2,
-                                              base::FEATURE_ENABLED_BY_DEFAULT),
-        {"209.18.47.61", "209.18.47.62", "2001:1998:0f00:0001::1",
-         "2001:1998:0f00:0002::1"},
-        /*dns_over_tls_hostnames=*/{},
-        "https://doh-02.spectrum.com/dns-query{?dns}",
-        /*ui_name=*/"",
-        /*privacy_policy=*/"",
-        /*display_globally=*/false,
-        /*display_countries=*/{},
-        LoggingLevel::kNormal}})));
+       {
+           "NextDns",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderNextDns, base::FEATURE_ENABLED_BY_DEFAULT),
+           /*dns_over_53_server_ip_strs=*/{},
+           /*dns_over_tls_hostnames=*/{},
+           "https://chromium.dns.nextdns.io",
+           /*ui_name=*/"NextDNS",
+           /*privacy_policy=*/"https://nextdns.io/privacy",
+           /*display_globally=*/false,
+           /*display_countries=*/{"US"},
+       },
+       {
+           "OpenDNS",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderOpenDNS, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"208.67.222.222", "208.67.220.220", "2620:119:35::35",
+            "2620:119:53::53"},
+           /*dns_over_tls_hostnames=*/{},
+           "https://doh.opendns.com/dns-query{?dns}",
+           /*ui_name=*/"OpenDNS",
+           "https://www.cisco.com/c/en/us/about/legal/"
+           /*privacy_policy=*/"privacy-full.html",
+           /*display_globally=*/true,
+           /*display_countries=*/{},
+       },
+       {
+           "OpenDNSFamily",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderOpenDNSFamily, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"208.67.222.123", "208.67.220.123", "2620:119:35::123",
+            "2620:119:53::123"},
+           /*dns_over_tls_hostnames=*/{},
+           "https://doh.familyshield.opendns.com/dns-query{?dns}",
+           /*ui_name=*/"",
+           /*privacy_policy=*/"",
+           /*display_globally=*/false,
+           /*display_countries=*/{},
+       },
+       {
+           "Quad9Cdn",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderQuad9Cdn, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"9.9.9.11", "149.112.112.11", "2620:fe::11", "2620:fe::fe:11"},
+           /*dns_over_tls_hostnames=*/{"dns11.quad9.net"},
+           "https://dns11.quad9.net/dns-query",
+           /*ui_name=*/"",
+           /*privacy_policy=*/"",
+           /*display_globally=*/false,
+           /*display_countries=*/{},
+       },
+       {
+           "Quad9Insecure",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderQuad9Insecure, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"9.9.9.10", "149.112.112.10", "2620:fe::10", "2620:fe::fe:10"},
+           /*dns_over_tls_hostnames=*/{"dns10.quad9.net"},
+           "https://dns10.quad9.net/dns-query",
+           /*ui_name=*/"",
+           /*privacy_policy=*/"",
+           /*display_globally=*/false,
+           /*display_countries=*/{},
+       },
+       {
+           "Quad9Secure",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderQuad9Secure, base::FEATURE_DISABLED_BY_DEFAULT),
+           {"9.9.9.9", "149.112.112.112", "2620:fe::fe", "2620:fe::9"},
+           /*dns_over_tls_hostnames=*/{"dns.quad9.net", "dns9.quad9.net"},
+           "https://dns.quad9.net/dns-query",
+           /*ui_name=*/"Quad9 (9.9.9.9)",
+           /*privacy_policy=*/"https://www.quad9.net/home/privacy/",
+           /*display_globally=*/true,
+           /*display_countries=*/{},
+       },
+       {
+           "Quickline",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderQuickline, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"212.60.61.246", "212.60.63.246", "2001:1a88:10:ffff::1",
+            "2001:1a88:10:ffff::2"},
+           /*dns_over_tls_hostnames=*/{"dot.quickline.ch"},
+           "https://doh.quickline.ch/dns-query{?dns}",
+           /*ui_name=*/"",
+           /*privacy_policy=*/"",
+           /*display_globally=*/false,
+           /*display_countries=*/{},
+       },
+       {
+           "Spectrum1",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderSpectrum1, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"209.18.47.61", "209.18.47.62", "2001:1998:0f00:0001::1",
+            "2001:1998:0f00:0002::1"},
+           /*dns_over_tls_hostnames=*/{},
+           "https://doh-01.spectrum.com/dns-query{?dns}",
+           /*ui_name=*/"",
+           /*privacy_policy=*/"",
+           /*display_globally=*/false,
+           /*display_countries=*/{},
+       },
+       {
+           "Spectrum2",
+           MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
+               DohProviderSpectrum2, base::FEATURE_ENABLED_BY_DEFAULT),
+           {"209.18.47.61", "209.18.47.62", "2001:1998:0f00:0001::1",
+            "2001:1998:0f00:0002::1"},
+           /*dns_over_tls_hostnames=*/{},
+           "https://doh-02.spectrum.com/dns-query{?dns}",
+           /*ui_name=*/"",
+           /*privacy_policy=*/"",
+           /*display_globally=*/false,
+           /*display_countries=*/{},
+       }})));
   // LINT.ThenChange(//tools/metrics/histograms/metadata/net/histograms.xml:DohProviderId)
 
   static const base::NoDestructor<DohProviderEntry::List> providers(
@@ -376,13 +409,11 @@
     std::string_view ui_name,
     std::string_view privacy_policy,
     bool display_globally,
-    base::flat_set<std::string> display_countries,
-    LoggingLevel logging_level) {
-  return DohProviderEntry(provider, feature, dns_over_53_server_ip_strs,
-                          std::move(dns_over_tls_hostnames),
-                          std::move(dns_over_https_template), ui_name,
-                          privacy_policy, display_globally,
-                          std::move(display_countries), logging_level);
+    base::flat_set<std::string> display_countries) {
+  return DohProviderEntry(
+      provider, feature, dns_over_53_server_ip_strs,
+      std::move(dns_over_tls_hostnames), std::move(dns_over_https_template),
+      ui_name, privacy_policy, display_globally, std::move(display_countries));
 }
 
 DohProviderEntry::~DohProviderEntry() = default;
@@ -397,7 +428,6 @@
     std::string_view privacy_policy,
     bool display_globally,
     base::flat_set<std::string> display_countries,
-    LoggingLevel logging_level,
     std::initializer_list<std::string_view> dns_over_https_server_ip_strs)
     : provider(provider),
       feature(*feature),
@@ -409,8 +439,7 @@
       ui_name(ui_name),
       privacy_policy(privacy_policy),
       display_globally(display_globally),
-      display_countries(std::move(display_countries)),
-      logging_level(logging_level) {
+      display_countries(std::move(display_countries)) {
   DCHECK(!display_globally || this->display_countries.empty());
   if (display_globally || !this->display_countries.empty()) {
     DCHECK(!this->ui_name.empty());
diff --git a/net/dns/public/doh_provider_entry.h b/net/dns/public/doh_provider_entry.h
index a6a1179..93a3045 100644
--- a/net/dns/public/doh_provider_entry.h
+++ b/net/dns/public/doh_provider_entry.h
@@ -43,15 +43,6 @@
  public:
   using List = std::vector<raw_ptr<const DohProviderEntry, VectorExperimental>>;
 
-  enum class LoggingLevel {
-    // Indicates the normal amount of logging, monitoring, and metrics.
-    kNormal,
-
-    // Indicates that a provider is of extra interest and eligible for
-    // additional logging, monitoring, and metrics.
-    kExtra,
-  };
-
   std::string_view provider;
   // Avoid using base::Feature& and use raw_ref instead. Use feature.get()
   // for accessing the raw reference.
@@ -63,7 +54,6 @@
   std::string_view privacy_policy;
   bool display_globally;
   base::flat_set<std::string> display_countries;
-  LoggingLevel logging_level;
 
   // Returns the full list of DoH providers. A subset of this list may be used
   // to support upgrade in automatic mode or to populate the dropdown menu for
@@ -79,8 +69,7 @@
       std::string_view ui_name,
       std::string_view privacy_policy,
       bool display_globally,
-      base::flat_set<std::string> display_countries,
-      LoggingLevel logging_level = LoggingLevel::kNormal);
+      base::flat_set<std::string> display_countries);
 
   // Entries are neither copyable nor moveable. This allows tests to construct a
   // List but ensures that `const DohProviderEntry*` is a safe type for
@@ -105,7 +94,6 @@
       std::string_view privacy_policy,
       bool display_globally,
       base::flat_set<std::string> display_countries,
-      LoggingLevel logging_level,
       std::initializer_list<std::string_view> dns_over_https_server_ip_strs =
           {});
 };
diff --git a/net/dns/resolve_context.cc b/net/dns/resolve_context.cc
index ac5ffdd6..632a98d 100644
--- a/net/dns/resolve_context.cc
+++ b/net/dns/resolve_context.cc
@@ -57,28 +57,6 @@
 // Number of samples to seed the histogram with.
 const base::HistogramBase::Count32 kNumSeeds = 2;
 
-DohProviderEntry::List FindDohProvidersMatchingServerConfig(
-    DnsOverHttpsServerConfig server_config) {
-  DohProviderEntry::List matching_entries;
-  for (const DohProviderEntry* entry : DohProviderEntry::GetList()) {
-    if (entry->doh_server_config == server_config)
-      matching_entries.push_back(entry);
-  }
-
-  return matching_entries;
-}
-
-DohProviderEntry::List FindDohProvidersAssociatedWithAddress(
-    IPAddress server_address) {
-  DohProviderEntry::List matching_entries;
-  for (const DohProviderEntry* entry : DohProviderEntry::GetList()) {
-    if (entry->ip_addresses.count(server_address) > 0)
-      matching_entries.push_back(entry);
-  }
-
-  return matching_entries;
-}
-
 base::TimeDelta GetDefaultFallbackPeriod(const DnsConfig& config) {
   NetworkChangeNotifier::ConnectionType type =
       NetworkChangeNotifier::GetConnectionType();
@@ -556,16 +534,15 @@
 
   std::string query_type =
       GetQueryTypeForUma(server_index, is_doh_server, session);
-  std::string provider_id =
-      GetDohProviderIdForUma(server_index, is_doh_server, session);
 
-  // Skip metrics for SecureNotValidated queries unless the provider is tagged
-  // for extra logging.
-  if (query_type == "SecureNotValidated" &&
-      !GetProviderUseExtraLogging(server_index, is_doh_server, session)) {
+  // Skip metrics for SecureNotValidated queries.
+  if (query_type == "SecureNotValidated") {
     return;
   }
 
+  std::string provider_id =
+      GetDohProviderIdForUma(server_index, is_doh_server, session);
+
   if (rv == OK || rv == ERR_NAME_NOT_RESOLVED) {
     base::UmaHistogramMediumTimes(
         base::JoinString(
@@ -610,29 +587,6 @@
       session->config().nameservers[server_index]);
 }
 
-bool ResolveContext::GetProviderUseExtraLogging(size_t server_index,
-                                                bool is_doh_server,
-                                                const DnsSession* session) {
-  DCHECK(IsCurrentSession(session));
-
-  DohProviderEntry::List matching_entries;
-  if (is_doh_server) {
-    const DnsOverHttpsServerConfig& server_config =
-        session->config().doh_config.servers()[server_index];
-    matching_entries = FindDohProvidersMatchingServerConfig(server_config);
-  } else {
-    IPAddress server_address =
-        session->config().nameservers[server_index].address();
-    matching_entries = FindDohProvidersAssociatedWithAddress(server_address);
-  }
-
-  // Use extra logging if any matching provider entries have
-  // `LoggingLevel::kExtra` set.
-  return std::ranges::contains(matching_entries,
-                               DohProviderEntry::LoggingLevel::kExtra,
-                               &DohProviderEntry::logging_level);
-}
-
 void ResolveContext::NotifyDohStatusObserversOfSessionChanged() {
   for (auto& observer : doh_status_observers_)
     observer.OnSessionChanged();
diff --git a/net/dns/resolve_context.h b/net/dns/resolve_context.h
index 2208e0b..633e732 100644
--- a/net/dns/resolve_context.h
+++ b/net/dns/resolve_context.h
@@ -293,9 +293,6 @@
   std::string GetDohProviderIdForUma(size_t server_index,
                                      bool is_doh_server,
                                      const DnsSession* session);
-  bool GetProviderUseExtraLogging(size_t server_index,
-                                  bool is_doh_server,
-                                  const DnsSession* session);
 
   void NotifyDohStatusObserversOfSessionChanged();
   void NotifyDohStatusObserversOfUnavailable(bool network_change);
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index 6da59e7f..a112626 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -127,6 +127,9 @@
   // Convenience function that combines WaitForConnect() and Complete().
   void WaitForConnectAndComplete(int result);
 
+  // Returns true if the completer has a waiting connection attempt.
+  bool is_connecting() const { return !callback_.is_null(); }
+
  private:
   friend class MockTCPClientSocket;
   friend class MockSSLClientSocket;
diff --git a/net/socket/tcp_connect_job.cc b/net/socket/tcp_connect_job.cc
index a2546e76..2aac11a 100644
--- a/net/socket/tcp_connect_job.cc
+++ b/net/socket/tcp_connect_job.cc
@@ -66,7 +66,7 @@
                  NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT),
       params_(params),
       endpoint_override_(std::move(endpoint_result_override)),
-      connector_(std::make_unique<Connector>(this)) {
+      primary_connector_(std::make_unique<Connector>(this)) {
   if (endpoint_override_) {
     UpdateSvcbOptional();
     DCHECK(!endpoint_override_->endpoints.front().ipv4_endpoints.empty() ||
@@ -79,7 +79,14 @@
 
 LoadState TcpConnectJob::GetLoadState() const {
   // TODO(https://crbug.com/484073410): Test this.
-  return connector_->GetLoadState();
+  LoadState load_state = primary_connector_->GetLoadState();
+  // This method should return LOAD_STATE_CONNECTING in preference to
+  // LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET when possible because "waiting
+  // for available socket" implies that nothing is happening.
+  if (ipv4_connector_ && load_state != LOAD_STATE_CONNECTING) {
+    load_state = ipv4_connector_->GetLoadState();
+  }
+  return load_state;
 }
 
 bool TcpConnectJob::HasEstablishedConnection() const {
@@ -123,6 +130,13 @@
   return base::Minutes(4);
 }
 
+bool TcpConnectJob::has_two_connectors_for_testing() const {
+  CHECK(!is_done_);
+  // `primary_connector_` should never be nullptr.
+  CHECK(primary_connector_);
+  return ipv4_connector_.get() != nullptr;
+}
+
 int TcpConnectJob::ConnectInternal() {
   int rv = OK;
   if (!endpoint_override_) {
@@ -157,6 +171,10 @@
   DCHECK(!is_done_);
   DCHECK(!dns_request_complete_);
 
+  // Reset progress through endpoint results, as new ones may have been inserted
+  // before the one that was currently under consideration.
+  current_service_endpoint_index_ = 0;
+
   bool did_fail = false;
   if (dns_request_final_result) {
     DCHECK_NE(*dns_request_final_result, ERR_IO_PENDING);
@@ -193,18 +211,79 @@
   return DoTryAdvanceWaitingConnectors();
 }
 
+void TcpConnectJob::TryAdvanceWaitingConnectorsAsync() {
+  // These `is_done_` checks my be be hit if the consumer doesn't delete `this`
+  // immediately on completion.
+  //
+  // TODO(https://crbug.com/484073410): Either test this, or figure out a better
+  // option..
+  if (is_done_) {
+    return;
+  }
+
+  NotifyDelegateIfDone(DoTryAdvanceWaitingConnectors());
+}
+
 int TcpConnectJob::DoTryAdvanceWaitingConnectors() {
   DCHECK(!is_done_);
-  DCHECK(!connector_->is_done());
+  DCHECK(!primary_connector_->is_done() ||
+         (ipv4_connector_ && !ipv4_connector_->is_done()));
 
-  if (!connector_->is_done()) {
-    int rv = connector_->OnEndpointDataAvailable();
-    if (rv != ERR_IO_PENDING) {
-      return SetDone(rv);
+  // Note that `primary_connector_` and `ipv4_connector_` are only deleted when
+  // DoConnectorComplete() returns a value other than ERR_IO_PENDING, and
+  // `ipv4_connector_` is only created from the slower timer callback, so this
+  // is safe.
+  for (Connector* connector :
+       {primary_connector_.get(), ipv4_connector_.get()}) {
+    if (connector && !connector->is_done()) {
+      int rv = connector->TryAdvanceState();
+      if (rv != ERR_IO_PENDING) {
+        // The connection attempt completed synchronously. Call
+        // DoConnectorComplete() to handle the result, and learn if the entire
+        // ConnectJob is complete.
+        rv = DoConnectorComplete(rv, *connector);
+        if (rv != ERR_IO_PENDING) {
+          return rv;
+        }
+      }
     }
   }
 
-  // TODO(https://crbug.com/484073410) Add a second Connector after some delay.
+  // If we reach this point, There should still be work to do.
+  DCHECK(!is_done_);
+  DCHECK(!primary_connector_->is_done() ||
+         (ipv4_connector_ && !ipv4_connector_->is_done()));
+
+  // If there is only a single connector, and we've started trying to connect,
+  // and the slow timer isn't running, start the slow timer.
+  //
+  // This could result in starting the slow timer if we, e.g., we're already
+  // trying to final IP and no more IPs are coming, but this keeps things
+  // simple.
+  if (!ipv4_connector_ && !slow_timer_.IsRunning() &&
+      !attempted_addresses_.empty()) {
+    slow_timer_.Start(
+        FROM_HERE, kIPv6FallbackTime,
+        base::BindOnce(&TcpConnectJob::OnSlow, base::Unretained(this)));
+  }
+
+  return ERR_IO_PENDING;
+}
+
+int TcpConnectJob::DoConnectorComplete(int result, Connector& connector) {
+  DCHECK_NE(result, ERR_IO_PENDING);
+  // Once one connector succeeds, no need to wait for the other. Also treat
+  // ERR_NETWORK_IO_SUSPENDED as a failure for both connectors.
+  if (result == OK || result == ERR_NETWORK_IO_SUSPENDED) {
+    return SetDone(result, &connector);
+  }
+
+  // If both connectors have failed, we're also done.
+  if (primary_connector_->is_done() &&
+      (!ipv4_connector_ || ipv4_connector_->is_done())) {
+    return SetDone(result, &connector);
+  }
+
   return ERR_IO_PENDING;
 }
 
@@ -230,29 +309,94 @@
       DoServiceEndpointsUpdated(/*dns_request_final_result=*/rv));
 }
 
-void TcpConnectJob::OnConnectorComplete(int result) {
-  NotifyDelegateOfCompletion(SetDone(result));
+void TcpConnectJob::OnConnectorComplete(int result, Connector& connector) {
+  int rv = DoConnectorComplete(result, connector);
+  if (rv != ERR_IO_PENDING) {
+    NotifyDelegateOfCompletion(rv);
+  }
 }
 
-TcpConnectJob::IPEndPointInfo TcpConnectJob::GetNextIPEndPoint() {
+void TcpConnectJob::OnSlow() {
   DCHECK(!is_done_);
-  DCHECK(!connector_->is_done());
+  DCHECK(!ipv4_connector_);
 
-  for (const auto& service_endpoint : GetEndpointResults()) {
-    if (!IsEndpointResultUsable(service_endpoint)) {
-      continue;
+  // Make a second connector, so have separate IPv4 and IPv6 connectors. The
+  // `primary_connector_` may be waiting for an IP, or doing either a v4 or v6
+  // lookup. If it's doing a v4 lookup, move it into `ipv4_connector_`.
+  ipv4_connector_ = std::make_unique<Connector>(this);
+  if (!primary_connector_->is_connecting_to_ipv6()) {
+    std::swap(primary_connector_, ipv4_connector_);
+  }
+
+  TryAdvanceWaitingConnectorsAsync();
+}
+
+TcpConnectJob::IPEndPointInfo TcpConnectJob::GetNextIPEndPoint(
+    const Connector& connector) {
+  const auto& service_endpoints = GetEndpointResults();
+  DCHECK(!is_done_);
+  DCHECK(!connector.is_done());
+
+  // Other job, if any, for checking its state, and advancing it if necessary.
+  const Connector* other_job =
+      (&connector == primary_connector_.get() ? ipv4_connector_.get()
+                                              : primary_connector_.get());
+
+  // Note that this will make both jobs use IPv4/IPv6, once there are no more
+  // IPs of the other type. Not clear if that's a concern. Not too difficult to
+  // change behavior - only checking IPv4 or IPv6 when there are two jobs should
+  // be sufficient. `current_service_endpoint_index_` logic will still work
+  // correctly.
+  bool prefer_ipv6 = prefer_ipv6_;
+  if (ipv4_connector_) {
+    prefer_ipv6 = (primary_connector_.get() == &connector);
+  }
+
+  bool posted_resume_task = false;
+
+  while (current_service_endpoint_index_ < service_endpoints.size()) {
+    const auto& service_endpoint =
+        service_endpoints[current_service_endpoint_index_];
+    if (IsEndpointResultUsable(service_endpoint)) {
+      for (bool ip_v6 : {prefer_ipv6, !prefer_ipv6}) {
+        const auto& ip_endpoints = ip_v6 ? service_endpoint.ipv6_endpoints
+                                         : service_endpoint.ipv4_endpoints;
+        for (const auto& ip_endpoint : ip_endpoints) {
+          // If `ip_endpoint` hasn't been tried yet, add it to
+          // `attempted_addresses_` and we will return it.
+          auto [it, inserted] = attempted_addresses_.emplace(ip_endpoint);
+          if (inserted) {
+            return ip_endpoint;
+          }
+        }
+      }
     }
 
-    for (bool ip_v6 : {prefer_ipv6_, !prefer_ipv6_}) {
-      const auto& ip_endpoints = ip_v6 ? service_endpoint.ipv6_endpoints
-                                       : service_endpoint.ipv4_endpoints;
-      for (const auto& ip_endpoint : ip_endpoints) {
-        if (attempted_addresses_.contains(ip_endpoint)) {
-          continue;
-        }
-        attempted_addresses_.emplace(ip_endpoint);
-        return ip_endpoint;
-      }
+    // Only move on to the next endpoint if either there's no other connector,
+    // or the other connector is waiting to receive an endpoint. Since new
+    // results may come in out of order, this isn't perfect - e.g., could
+    // still be connecting to a AAAA record when HTTPS records come in. Then
+    // the AAAA connection attempt could block connection attempts to the
+    // second ServiceEndpoint entry (and could block the second job from
+    // trying the next A/AAAA entry as well, if the HTTPS record connection
+    // attempts fail quickly). Could throw away the AAAA attempt in that case,
+    // or have logic to detect it, but this seems a reasonable balance of
+    // accuracy, complexity, and performance.
+    if (other_job && !other_job->is_waiting_for_endpoint()) {
+      // Need to wait for other jobs to complete.
+      return base::unexpected(ERR_IO_PENDING);
+    }
+
+    ++current_service_endpoint_index_;
+    // May need to resume the other job after advancing to the next result.
+    if (other_job && !posted_resume_task) {
+      // Small optimization to avoid posting multiple tasks at once - probably
+      // not really needed. Nothing would break without it.
+      posted_resume_task = true;
+      base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
+          FROM_HERE,
+          base::BindOnce(&TcpConnectJob::TryAdvanceWaitingConnectorsAsync,
+                         weak_ptr_factory_.GetWeakPtr()));
     }
   }
 
@@ -339,16 +483,17 @@
   }
 }
 
-int TcpConnectJob::SetDone(int result) {
+int TcpConnectJob::SetDone(int result, Connector* connector) {
   DCHECK(!is_done_);
   DCHECK(!final_address_);
 
   if (result == OK) {
     DCHECK(EndpointsCryptoReady());
-    DCHECK(IsIPEndPointUsable(connector_->CurrentAddress()));
+    DCHECK(connector);
+    DCHECK(IsIPEndPointUsable(connector->CurrentAddress()));
 
-    SetSocket(connector_->PassSocket(), GetDnsAliasResults());
-    final_address_ = connector_->CurrentAddress();
+    SetSocket(connector->PassSocket(), GetDnsAliasResults());
+    final_address_ = connector->CurrentAddress();
   } else {
     // If there were no attempts, there were no usable addresses. Use `result`
     // in that case.
@@ -368,7 +513,9 @@
     dns_request_.reset();
   }
 
-  connector_.reset();
+  slow_timer_.Stop();
+  primary_connector_.reset();
+  ipv4_connector_.reset();
   is_done_ = true;
 
   return result;
diff --git a/net/socket/tcp_connect_job.h b/net/socket/tcp_connect_job.h
index 272476d..caa601f 100644
--- a/net/socket/tcp_connect_job.h
+++ b/net/socket/tcp_connect_job.h
@@ -47,12 +47,12 @@
 //
 // Since this class runs the DNS request in parallel with trying multiple
 // connection attempts, it doesn't use a DoLoop() pattern often found in net.
-// Instead, it has two primary methods that manage reacting to state updates:
-// DoServiceEndpointsUpdated() and DoTryAdvanceWaitingConnectors(). Each of
-// those methods returns a net::Error representing the progress of the
-// TcpConnectJob as a whole, and so can be called either synchronously or
-// asynchronously. If the caller invoking them is async, it's expected to call
-// NotifyDelegateOfCompletion() itself.
+// Instead, it has three primary methods that manage reacting to state updates:
+// DoServiceEndpointsUpdated(), DoTryAdvanceWaitingConnectors(), and
+// DoConnectorComplete(). Each of those methods returns a net::Error
+// representing the progress of the TcpConnectJob as a whole, and so can be
+// called either synchronously or asynchronously. If the caller invoking them is
+// async, it's expected to call NotifyDelegateOfCompletion() itself.
 class NET_EXPORT_PRIVATE TcpConnectJob
     : public ConnectJob,
       public HostResolver::ServiceEndpointRequest::Delegate {
@@ -113,6 +113,11 @@
 
   static base::TimeDelta ConnectionTimeout();
 
+  // Returns true if there are two live connectors. CHECKs if complete, since
+  // both connectors are deleted at that point, which is probably not what
+  // callers are trying to test.
+  bool has_two_connectors_for_testing() const;
+
  private:
   // Connectors manage the actual connection attempts. They keep on pulling
   // IP addresses to try from the TcpConnectJob and trying to connect to them
@@ -127,7 +132,7 @@
   int ConnectInternal() override;
   void ChangePriorityInternal(RequestPriority priority) override;
 
-  // One of the two principal methods running the the TcpConnectJob's state
+  // One of the three principal methods running the the TcpConnectJob's state
   // machine. Returns either final error code of the TcpConnectJob if complete,
   // or ERR_IO_PENDING if not.
   //
@@ -136,36 +141,59 @@
   // which the request finished.
   int DoServiceEndpointsUpdated(std::optional<int> dns_request_final_result);
 
-  // One of the two principal methods running the the TcpConnectJob's state
+  // Method that can be posted to asynchronously call
+  // DoTryAdvanceWaitingConnectors() and will complete the TcpConnectJob if that
+  // returns something other than ERR_IO_PENDING.
+  void TryAdvanceWaitingConnectorsAsync();
+
+  // One of the three principal methods running the the TcpConnectJob's state
   // machine.
   //
   // Tells Connectors to check if what DNS data they're waiting on is now
   // available. Returns either final error code of the entire TcpConnectJob if
   // complete, or ERR_IO_PENDING if not.
   //
-  // Called when service endpoints are updated.
+  // Called when one of the following happens:
+  // * When service endpoints are updated.
+  // * When the slow timer triggers, and a second job is created.
+  // * When there are two connectors, called asynchronously by
+  //   GetNextIPEndPoint() through a posted TryAdvanceWaitingConnectorsAsync()
+  //   call whenever it advances `current_service_endpoint_index_`, to give the
+  //   other connector a chance to get an IP from the new ServiceEndpoint.
   int DoTryAdvanceWaitingConnectors();
 
+  // One of the three principal methods running the the TcpConnectJob's state
+  // machine.
+  //
+  // Called when a connector has completed - it has either failed to establish a
+  // usable connections, having tried all possible IP addresses (and the DNS
+  // resolution is complete), or it has a usable connection. Returns
+  // `ERR_IO_PENDING` if there's another connector that the job should wait on,
+  // or the final net::Error for the Job.
+  int DoConnectorComplete(int result, Connector& connector);
+
   // HostResolver::ServiceEndpointRequest:
   void OnServiceEndpointsUpdated() override;
   void OnServiceEndpointRequestFinished(int rv) override;
 
-  // Called back from a Connector when it completes. On failure, the last error
+  // Called back from `connector` when it completes. On failure, the last error
   // of `connection_attempts_` will be preferred over `result`, if there are any
   // errors there, since the error here will generally be ERR_NAME_NOT_RESOLVED
   // due to exhausting all provided IP addresses, rather than a connection
   // error.
-  void OnConnectorComplete(int result);
+  void OnConnectorComplete(int result, Connector& connector);
 
-  // Returns the next `IPEndPoint` that the Connector should connect to, and
-  // logs that endpoint has been attempted. Never returns the same IPEndPoint
-  // twice.
+  // Called by `slow_timer_`. Creates and starts `ipv4_connector_`.
+  void OnSlow();
+
+  // Returns the next `IPEndPoint` that `connector` should connect to, and logs
+  // that endpoint has been attempted. Never returns the same IPEndPoint twice.
   //
   // Returns ERR_NAME_NOT_RESOLVED if there are no more IPEndPoints, and never
   // will be any more (i.e., the DNS request must be completed), ERR_IO_PENDING
   // if none are available yet. On any fatal DNS error, all work is cancelled,
   // so this shouldn't return other error values.
-  IPEndPointInfo GetNextIPEndPoint();
+  IPEndPointInfo GetNextIPEndPoint(const Connector& connector);
 
   // Returns whether `result` is usable for this connection. If `svcb_optional`
   // is true, the non-HTTPS/SVCB fallback is allowed.
@@ -193,13 +221,15 @@
   // connected to an endpoint and ServiceEndpointRequest is crypto ready, or
   // we've given up on establishing a connection.
   //
-  // On success, takes the connected socket from the Connector and calls
-  // SetSocket(). On failure, returns the error from the last entry in
-  // `connection_attempts_`. If the array is empty, adds an entry in
+  // On success, takes the connected socket from `connector` and calls
+  // SetSocket().
+  //
+  // On failure, `connector` is ignored, and returns the error from the last
+  // entry in `connection_attempts_`. If the array is empty, adds an entry in
   // `connection_attempts_` with an empty IP and `result`, and then return
   // `result`. That can happen if there's a DNS error, or there are no usable
   // ServiceEndpoints.
-  int SetDone(int result);
+  int SetDone(int result, Connector* connector = nullptr);
 
   // These wrap the corresponding methods in `dns_request_`. They pull results
   // from `endpoint_override_` instead, if populated.
@@ -225,15 +255,44 @@
 
   std::unique_ptr<HostResolver::ServiceEndpointRequest> dns_request_;
   bool dns_request_complete_ = false;
+  // The index within the the ServiceEndpoint result of `dns_request_` that
+  // we're currently trying to connect to. Reset each time endpoint results are
+  // updated. This is both a performance optimization, to avoid searching
+  // through the same IPs again and again (Comparing them to
+  // `attempted_addresses_`), and has functional impact - it's only incremented
+  // once all endpoints within a ServiceEndpoint have been tried and failed,
+  // since they're in priority order.
+  size_t current_service_endpoint_index_ = 0;
 
-  std::unique_ptr<Connector> connector_;
+  // At the start, only `primary_connector_` is non-null, and will try to
+  // alternate connecting to IPv6 and IPv4 addresses, based on what's available
+  // and on `prefer_ipv6_`. Once the slow timer expires, there will always be
+  // two connectors, the primary always prefers to connect to IPv6 destinations,
+  // and `ipv4_connector_` will prefer IPv4 ones. If there are only untried IPv4
+  // or IPv6 addresses available in the ServiceEndpoint indicated by
+  // `current_service_endpoint_index_`, both jobs may try to connect to IPs of
+  // the same type. If the primary connector is doing an IPv4 resolution when
+  // the timer expires, it will be moved into the `ipv4_connector_` slot.
+  //
+  // This is a little awkward, but it avoids the need to swap active connectors
+  // when a connection attempt fails before we create a second Connector, so
+  // allows for a single function to resume a stalled connector on DNS complete,
+  // and a single function to get the next IP for the primary/secondary
+  // connector (which can be used by the resume function as well), and allows
+  // for sync completion of all calls when possible, without any post tasks,
+  // except when advancing `current_service_endpoint_index_`.
+  std::unique_ptr<TcpConnectJob::Connector> primary_connector_;
+  std::unique_ptr<TcpConnectJob::Connector> ipv4_connector_;
 
   // Set/cleared on error connecting to IPv6/IPv4. Affects what type of IP is
-  // preferred, if IPv6 and IPv4 IPs of equal priority are available.
+  // preferred, if IPv6 and IPv4 IPs of equal priority are available. Only
+  // matters when there's only one Connector.
   bool prefer_ipv6_ = true;
 
   ResolveErrorInfo resolve_error_info_;
 
+  base::OneShotTimer slow_timer_;
+
   // This includes addresses that Connectors are currently attempting to connect
   // to. No address will ever br tried twice, even if it appears in multiple
   // ServiceEndpoints.
@@ -264,6 +323,8 @@
   // calls that can't be cancelled coming in late, and to double-check that the
   // TcpConnectJob isn't completing twice.
   bool is_done_ = false;
+
+  base::WeakPtrFactory<TcpConnectJob> weak_ptr_factory_{this};
 };
 
 }  // namespace net
diff --git a/net/socket/tcp_connect_job_connector.cc b/net/socket/tcp_connect_job_connector.cc
index 26f1cef..adc780c 100644
--- a/net/socket/tcp_connect_job_connector.cc
+++ b/net/socket/tcp_connect_job_connector.cc
@@ -26,7 +26,7 @@
 
 TcpConnectJob::Connector::~Connector() = default;
 
-int TcpConnectJob::Connector::OnEndpointDataAvailable() {
+int TcpConnectJob::Connector::TryAdvanceState() {
   DCHECK(!is_done());
 
   if (next_state_ == State::kWaitForIPEndPoint) {
@@ -75,7 +75,7 @@
 void TcpConnectJob::Connector::OnIOComplete(int result) {
   int rv = DoLoop(result);
   if (rv != ERR_IO_PENDING) {
-    parent_->OnConnectorComplete(rv);
+    parent_->OnConnectorComplete(rv, *this);
     // `this` may be deleted here.
   }
 }
@@ -117,7 +117,8 @@
 int TcpConnectJob::Connector::DoObtainIPEndPoint() {
   DCHECK(!current_address_);
 
-  TcpConnectJob::IPEndPointInfo endpoint_info = parent_->GetNextIPEndPoint();
+  TcpConnectJob::IPEndPointInfo endpoint_info =
+      parent_->GetNextIPEndPoint(*this);
 
   if (!endpoint_info.has_value()) {
     if (endpoint_info.error() == ERR_IO_PENDING) {
diff --git a/net/socket/tcp_connect_job_connector.h b/net/socket/tcp_connect_job_connector.h
index 910670a..38a0d2c 100644
--- a/net/socket/tcp_connect_job_connector.h
+++ b/net/socket/tcp_connect_job_connector.h
@@ -43,13 +43,16 @@
 
   ~Connector();
 
-  // Called when there may be ServiceEndpoint data available for the connector
-  // to advance. If `next_state_` is one of the two waiting state, updates
-  // `next_state_` and runs DoLoop(). Otherwise, returns ERR_IO_PENDING, since
-  // busy with something else. Must not be called if already done. On error,
-  // may return ERR_NAME_NOT_RESOLVED, if all IPs have been exhausted, rather
-  // than the error from the most recent connection attempt.
-  int OnEndpointDataAvailable();
+  // If `next_state_` is one of the two waiting states, updates `next_state_`
+  // and runs DoLoop() to attempt to pull needed data from parent class's host
+  // resolution. Returns ERR_IO_PENDING or final net::Error code. If not in a
+  // waiting state, always returns ERR_IO_PENDING. Must not be called if already
+  // done. On error, may return ERR_NAME_NOT_RESOLVED, if all IPs have been
+  // exhausted, rather than the error from the most recent connection attempt.
+  //
+  // Needs to be called by the parent job whenever the host resolution may have
+  // data available the Connector hasn't observed yet.
+  int TryAdvanceState();
 
   LoadState GetLoadState() const;
 
@@ -61,8 +64,18 @@
   // once the connector has successfully completed.
   const IPEndPoint& CurrentAddress() const;
 
+  bool is_waiting_for_endpoint() const {
+    return next_state_ == State::kWaitForIPEndPoint;
+  }
   bool is_done() const { return next_state_ == State::kDone; }
 
+  // Whether `this` is currently connecting to an IPv6 IP, or is connected to
+  // one and waiting for DNS to make progress.
+  bool is_connecting_to_ipv6() const {
+    return current_address_ &&
+           current_address_->GetFamily() == ADDRESS_FAMILY_IPV6;
+  }
+
  private:
   // Note that while in either of the "Wait" states, this is waiting on more
   // ServiceEndpoint data. The parent ConnectJob signals that data may be
diff --git a/net/socket/tcp_connect_job_unittest.cc b/net/socket/tcp_connect_job_unittest.cc
index 49126d31..94b07ed 100644
--- a/net/socket/tcp_connect_job_unittest.cc
+++ b/net/socket/tcp_connect_job_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "net/socket/tcp_connect_job.h"
 
+#include <array>
 #include <memory>
 #include <optional>
 #include <string>
@@ -1433,5 +1434,608 @@
   }
 }
 
+/////////////////////////////////////////////////////////////
+// Tests below this point focus on the two-Connector case. //
+/////////////////////////////////////////////////////////////
+
+// If the first information that comes from DNS is slow, only one Connector is
+// used.
+TEST_F(TcpConnectJobTest, OneConnectorSlowDns) {
+  const auto service_endpoint =
+      CreateServiceEndpoint({kIpV4Endpoint1, kIpV6Endpoint1});
+
+  auto request = host_resolver_.AddFakeRequest();
+  MockConnectCompleter connect_completer;
+  AddConnect(MockConnect(&connect_completer), kIpV6Endpoint1);
+  AddConnect(MockConnect(ASYNC, OK), kIpV4Endpoint1);
+
+  EXPECT_THAT(InitAndStart(), IsError(ERR_IO_PENDING));
+  FastForwardBy(TcpConnectJob::kIPv6FallbackTime);
+
+  request->add_endpoint(service_endpoint)
+      .CallOnServiceEndpointRequestFinished(OK);
+  connect_completer.WaitForConnect();
+
+  EXPECT_FALSE(connect_job_->has_two_connectors_for_testing());
+  // Since there's only one Connector, the kIpV4Endpoint1 connection should
+  // still be pending.
+  EXPECT_FALSE(client_socket_factory_.AllDataProvidersUsed());
+
+  // Failing the first request should create a second.
+  connect_completer.Complete(ERR_FAILED);
+  EXPECT_TRUE(client_socket_factory_.AllDataProvidersUsed());
+
+  WaitForSuccess(
+      kIpV4Endpoint1, service_endpoint,
+      /*expected_connection_attempts=*/{{kIpV6Endpoint1, ERR_FAILED}});
+  EXPECT_TRUE(connect_job_->HasEstablishedConnection());
+}
+
+// Test the case where we create two Connectors, but one is never used, since
+// there's only one IP. There's no extra observable events here due to the
+// second connector, but good to make sure this case doesn't have observable
+// problems.
+TEST_F(TcpConnectJobTest, TwoConnectorsOneIpSuccess) {
+  const auto service_endpoint = CreateServiceEndpoint({kIpV4Endpoint1});
+  host_resolver_.ConfigureDefaultResolution()
+      .add_endpoint(service_endpoint)
+      .CompleteStartSynchronously(OK);
+
+  MockConnectCompleter connect_completer;
+  AddConnect(MockConnect(&connect_completer), kIpV4Endpoint1);
+
+  EXPECT_THAT(InitAndStart(), IsError(ERR_IO_PENDING));
+  connect_completer.WaitForConnect();
+  EXPECT_FALSE(connect_job_->has_two_connectors_for_testing());
+  FastForwardBy(TcpConnectJob::kIPv6FallbackTime);
+  EXPECT_TRUE(connect_job_->has_two_connectors_for_testing());
+
+  connect_completer.Complete(OK);
+  WaitForSuccess(kIpV4Endpoint1, service_endpoint);
+  EXPECT_TRUE(connect_job_->HasEstablishedConnection());
+}
+
+// Test the case where we create two Connectors, but one is never used, since
+// there's only one IP. In this case, we ultimately fail to establish any
+// connection. There's no extra observable events here due to the second
+// connector, but good to make sure this case doesn't have observable problems.
+TEST_F(TcpConnectJobTest, TwoConnectorsOneIpFailure) {
+  const auto service_endpoint = CreateServiceEndpoint({kIpV4Endpoint1});
+  host_resolver_.ConfigureDefaultResolution()
+      .add_endpoint(service_endpoint)
+      .CompleteStartSynchronously(OK);
+
+  MockConnectCompleter connect_completer;
+  AddConnect(MockConnect(&connect_completer), kIpV4Endpoint1);
+
+  EXPECT_THAT(InitAndStart(), IsError(ERR_IO_PENDING));
+  connect_completer.WaitForConnect();
+  EXPECT_FALSE(connect_job_->has_two_connectors_for_testing());
+  FastForwardBy(TcpConnectJob::kIPv6FallbackTime);
+  EXPECT_TRUE(connect_job_->has_two_connectors_for_testing());
+
+  connect_completer.Complete(ERR_FAILED);
+  WaitForError(ERR_FAILED,
+               /*expected_connection_attempts=*/{{kIpV4Endpoint1, ERR_FAILED}});
+  EXPECT_FALSE(connect_job_->HasEstablishedConnection());
+}
+
+// Test the case where we create two Connectors, but one is never used, since
+// there's only one remaining IP when it's created. There's no extra observable
+// events here due to the second connector, but good to make sure this case
+// doesn't have observable problems.
+TEST_F(TcpConnectJobTest, TwoConnectorsOneUsedTwoIpsSuccess) {
+  const auto service_endpoint =
+      CreateServiceEndpoint({kIpV4Endpoint1, kIpV6Endpoint1});
+  host_resolver_.ConfigureDefaultResolution()
+      .add_endpoint(service_endpoint)
+      .CompleteStartSynchronously(OK);
+
+  AddConnect(MockConnect(ASYNC, ERR_FAILED), kIpV6Endpoint1);
+  MockConnectCompleter connect_completer;
+  AddConnect(MockConnect(&connect_completer), kIpV4Endpoint1);
+
+  base::Time start_time = base::Time::Now();
+  EXPECT_THAT(InitAndStart(), IsError(ERR_IO_PENDING));
+  connect_completer.WaitForConnect();
+  // Check time to make sure that the IPv4 Connector wasn't created.
+  EXPECT_EQ(base::Time::Now() - start_time, base::TimeDelta());
+  EXPECT_FALSE(connect_job_->has_two_connectors_for_testing());
+  FastForwardBy(TcpConnectJob::kIPv6FallbackTime);
+  EXPECT_TRUE(connect_job_->has_two_connectors_for_testing());
+
+  connect_completer.Complete(OK);
+  WaitForSuccess(
+      kIpV4Endpoint1, service_endpoint,
+      /*expected_connection_attempts=*/{{kIpV6Endpoint1, ERR_FAILED}});
+  EXPECT_TRUE(connect_job_->HasEstablishedConnection());
+}
+
+// Test the case where we make two Connectors with two IPs. Once succeeds, one
+// never completes.
+TEST_F(TcpConnectJobTest, TwoConnectorsTwoIpsOneNeverCompletes) {
+  const auto service_endpoint =
+      CreateServiceEndpoint({kIpV4Endpoint1, kIpV6Endpoint1});
+
+  // 0 indicates the first Connector successfully connects to kIpV6Endpoint1,
+  // while 1 indicates the second one successfully connects to kIpV4Endpoint1.
+  for (size_t successful_index : {0u, 1u}) {
+    base::Time start_time = base::Time::Now();
+
+    host_resolver_.ConfigureDefaultResolution()
+        .add_endpoint(service_endpoint)
+        .CompleteStartSynchronously(OK);
+
+    std::array<MockConnectCompleter, 2> connect_completers;
+    AddConnect(MockConnect(&connect_completers[0]), kIpV6Endpoint1);
+    AddConnect(MockConnect(&connect_completers[1]), kIpV4Endpoint1);
+
+    EXPECT_THAT(InitAndStart(), IsError(ERR_IO_PENDING));
+    connect_completers[0].WaitForConnect();
+    EXPECT_FALSE(connect_job_->has_two_connectors_for_testing());
+    EXPECT_EQ(base::Time::Now() - start_time, base::TimeDelta());
+
+    // Wait for the second Connector to start, which should mean the fallback
+    // time has passed.
+    connect_completers[1].WaitForConnect();
+    EXPECT_TRUE(connect_job_->has_two_connectors_for_testing());
+    EXPECT_EQ(base::Time::Now() - start_time, TcpConnectJob::kIPv6FallbackTime);
+
+    connect_completers[successful_index].Complete(OK);
+
+    WaitForSuccess(successful_index == 0 ? kIpV6Endpoint1 : kIpV4Endpoint1,
+                   service_endpoint);
+  }
+}
+
+// Test the case where we make two Connectors with two IPs. Once fails, one
+// succeeds.
+TEST_F(TcpConnectJobTest, TwoConnectorsTwoIpsOneFails) {
+  const auto service_endpoint =
+      CreateServiceEndpoint({kIpV4Endpoint1, kIpV6Endpoint1});
+
+  // 0 indicates the first Connector successfully connects to kIpV6Endpoint1,
+  // while 1 indicates the second one successfully connects to kIpV4Endpoint1.
+  for (size_t successful_index : {0u, 1u}) {
+    base::Time start_time = base::Time::Now();
+
+    host_resolver_.ConfigureDefaultResolution()
+        .add_endpoint(service_endpoint)
+        .CompleteStartSynchronously(OK);
+
+    std::array<MockConnectCompleter, 2> connect_completers;
+    AddConnect(MockConnect(&connect_completers[0]), kIpV6Endpoint1);
+    AddConnect(MockConnect(&connect_completers[1]), kIpV4Endpoint1);
+
+    EXPECT_THAT(InitAndStart(), IsError(ERR_IO_PENDING));
+    connect_completers[0].WaitForConnect();
+    EXPECT_FALSE(connect_job_->has_two_connectors_for_testing());
+    EXPECT_EQ(base::Time::Now() - start_time, base::TimeDelta());
+
+    // Wait for the second Connector to start, which should mean the fallback
+    // time has passed.
+    connect_completers[1].WaitForConnect();
+    EXPECT_TRUE(connect_job_->has_two_connectors_for_testing());
+    EXPECT_EQ(base::Time::Now() - start_time, TcpConnectJob::kIPv6FallbackTime);
+
+    connect_completers[1 - successful_index].Complete(ERR_FAILED);
+    connect_completers[successful_index].Complete(OK);
+
+    WaitForSuccess(successful_index == 0 ? kIpV6Endpoint1 : kIpV4Endpoint1,
+                   service_endpoint,
+                   /*expected_connection_attempts=*/
+                   {{successful_index == 0 ? kIpV4Endpoint1 : kIpV6Endpoint1,
+                     ERR_FAILED}});
+  }
+}
+
+// Test the case where we make two Connectors with two IPs. Both fail with
+// different errors.
+TEST_F(TcpConnectJobTest, TwoConnectorsTwoIpsBothFail) {
+  const std::vector<IPEndPoint> endpoints = {kIpV6Endpoint1, kIpV4Endpoint1};
+  const std::vector<Error> errors = {ERR_FAILED, ERR_UNEXPECTED};
+  const auto service_endpoint = CreateServiceEndpoint(endpoints);
+  // The errors for each endpoint.
+
+  // 0 indicates the first Connector fails first, while 1 indicates the second
+  // one successfully does. Failure order should be reflected in the returned
+  // error and the order of the connection attempts.
+  for (size_t first_failure : {0u, 1u}) {
+    int second_failure = 1 - first_failure;
+    base::Time start_time = base::Time::Now();
+
+    host_resolver_.ConfigureDefaultResolution()
+        .add_endpoint(service_endpoint)
+        .CompleteStartSynchronously(OK);
+
+    std::array<MockConnectCompleter, 2> connect_completers;
+    AddConnect(MockConnect(&connect_completers[0]), kIpV6Endpoint1);
+    AddConnect(MockConnect(&connect_completers[1]), kIpV4Endpoint1);
+
+    EXPECT_THAT(InitAndStart(), IsError(ERR_IO_PENDING));
+    connect_completers[0].WaitForConnect();
+    EXPECT_FALSE(connect_job_->has_two_connectors_for_testing());
+    EXPECT_EQ(base::Time::Now() - start_time, base::TimeDelta());
+
+    // Wait for the second Connector to start, which should mean the fallback
+    // time has passed.
+    connect_completers[1].WaitForConnect();
+    EXPECT_TRUE(connect_job_->has_two_connectors_for_testing());
+    EXPECT_EQ(base::Time::Now() - start_time, TcpConnectJob::kIPv6FallbackTime);
+
+    connect_completers[first_failure].Complete(errors[first_failure]);
+    connect_completers[second_failure].Complete(errors[second_failure]);
+
+    WaitForError(errors[second_failure],
+                 /*expected_connection_attempts=*/{
+                     {endpoints[first_failure], errors[first_failure]},
+                     {endpoints[second_failure], errors[second_failure]}});
+  }
+}
+
+// Test the case where there is basically always both an IPv4 and IPv6 IP
+// available, and that each Connector prefers one or the other. There's only a
+// single ServiceEndpoint in this test.
+TEST_F(TcpConnectJobTest, TwoConnectorsSixIps) {
+  const auto service_endpoint =
+      CreateServiceEndpoint({kIpV4Endpoint1, kIpV4Endpoint2, kIpV4Endpoint3,
+                             kIpV6Endpoint1, kIpV6Endpoint2, kIpV6Endpoint3});
+
+  base::Time start_time = base::Time::Now();
+
+  host_resolver_.ConfigureDefaultResolution()
+      .add_endpoint(service_endpoint)
+      .CompleteStartSynchronously(OK);
+
+  std::array<MockConnectCompleter, 6> connect_completers;
+  // Note that this order is based on the order in which of the previous
+  // connection attempts fails first.
+  AddConnect(MockConnect(&connect_completers[0]), kIpV6Endpoint1);
+  AddConnect(MockConnect(&connect_completers[1]), kIpV4Endpoint1);
+  AddConnect(MockConnect(&connect_completers[2]), kIpV4Endpoint2);
+  AddConnect(MockConnect(&connect_completers[3]), kIpV6Endpoint2);
+  AddConnect(MockConnect(&connect_completers[4]), kIpV6Endpoint3);
+  AddConnect(MockConnect(&connect_completers[5]), kIpV4Endpoint3);
+
+  EXPECT_THAT(InitAndStart(), IsError(ERR_IO_PENDING));
+
+  connect_completers[0].WaitForConnect();
+  EXPECT_FALSE(connect_job_->has_two_connectors_for_testing());
+  EXPECT_EQ(base::Time::Now() - start_time, base::TimeDelta());
+
+  // Wait for the second Connector to start, which should mean the fallback time
+  // has passed.
+  connect_completers[1].WaitForConnect();
+  EXPECT_TRUE(connect_job_->has_two_connectors_for_testing());
+  EXPECT_EQ(base::Time::Now() - start_time, TcpConnectJob::kIPv6FallbackTime);
+
+  // kIpV4Endpoint1 fails. The IPv4 Connector should try kIpV4Endpoint2.
+  connect_completers[1].Complete(ERR_FAILED);
+  connect_completers[2].WaitForConnect();
+
+  // kIpV6Endpoint1 fails. The primary Connector should try kIpV6Endpoint2, and
+  // after that fails, kIpV6Endpoint3.
+  connect_completers[0].Complete(ERR_UNEXPECTED);
+  connect_completers[3].WaitForConnectAndComplete(ERR_UNEXPECTED);
+  connect_completers[4].WaitForConnect();
+
+  // kIpV4Endpoint2 fails. The IPv4 Connector should try kIpV4Endpoint3, which
+  // also fails.
+  connect_completers[2].Complete(ERR_UNEXPECTED);
+  connect_completers[5].WaitForConnectAndComplete(ERR_FAILED);
+
+  // kIpV6Endpoint3 succeeds, completing the request.
+  connect_completers[4].Complete(OK);
+
+  WaitForSuccess(kIpV6Endpoint3, service_endpoint,
+                 /*expected_connection_attempts=*/
+                 {{kIpV4Endpoint1, ERR_FAILED},
+                  {kIpV6Endpoint1, ERR_UNEXPECTED},
+                  {kIpV6Endpoint2, ERR_UNEXPECTED},
+                  {kIpV4Endpoint2, ERR_UNEXPECTED},
+                  {kIpV4Endpoint3, ERR_FAILED}});
+  // No more time should have passed since the slow job was started, since time
+  // wasn't simulated advancing, and there should have been no other timed delay
+  // by TcpConnectJob.
+  EXPECT_EQ(base::Time::Now() - start_time, TcpConnectJob::kIPv6FallbackTime);
+}
+
+// Test the case where there are two Connectors, and all the IPv6 IPs come in
+// and fail and only then do the IPv4 ones come in. both Connectors should try
+// both IPv4 and IPv6 IPs. There's only a single ServiceEndpoint in this test,
+// though it's updated half-way through.
+TEST_F(TcpConnectJobTest, TwoConnectorsIPv6ThenIpv4) {
+  const auto service_endpoint = CreateServiceEndpoint(
+      {kIpV6Endpoint1, kIpV6Endpoint2, kIpV6Endpoint3, kIpV6Endpoint4,
+       kIpV4Endpoint1, kIpV4Endpoint2, kIpV4Endpoint3, kIpV4Endpoint4});
+
+  base::Time start_time = base::Time::Now();
+
+  auto request = host_resolver_.AddFakeRequest();
+
+  std::array<MockConnectCompleter, 8> connect_completers;
+  AddConnect(MockConnect(&connect_completers[0]), kIpV6Endpoint1);
+  AddConnect(MockConnect(&connect_completers[1]), kIpV6Endpoint2);
+  AddConnect(MockConnect(&connect_completers[2]), kIpV6Endpoint3);
+  AddConnect(MockConnect(&connect_completers[3]), kIpV6Endpoint4);
+  AddConnect(MockConnect(&connect_completers[4]), kIpV4Endpoint1);
+  AddConnect(MockConnect(&connect_completers[5]), kIpV4Endpoint2);
+  AddConnect(MockConnect(&connect_completers[6]), kIpV4Endpoint3);
+  AddConnect(MockConnect(&connect_completers[7]), kIpV4Endpoint4);
+
+  EXPECT_THAT(InitAndStart(), IsError(ERR_IO_PENDING));
+  // Temporary endpoint that only includes AAAA results.
+  request
+      ->add_endpoint(CreateServiceEndpoint(
+          {kIpV6Endpoint1, kIpV6Endpoint2, kIpV6Endpoint3, kIpV6Endpoint4}))
+      .CallOnServiceEndpointsUpdated();
+
+  connect_completers[0].WaitForConnect();
+  EXPECT_FALSE(connect_job_->has_two_connectors_for_testing());
+  EXPECT_EQ(base::Time::Now() - start_time, base::TimeDelta());
+
+  // Wait for the second Connector to start, which should mean the fallback time
+  // has passed.
+  connect_completers[1].WaitForConnect();
+  EXPECT_TRUE(connect_job_->has_two_connectors_for_testing());
+  EXPECT_EQ(base::Time::Now() - start_time, TcpConnectJob::kIPv6FallbackTime);
+
+  // kIpV6Endpoint2 fails. The IPv4 Connector should try kIpV6Endpoint3.
+  connect_completers[1].Complete(ERR_FAILED);
+  connect_completers[2].WaitForConnect();
+
+  // kIpV6Endpoint1 fails. The primary Connector should try kIpV6Endpoint4,
+  // which also fails.
+  connect_completers[0].Complete(ERR_FAILED);
+  connect_completers[3].WaitForConnectAndComplete(ERR_UNEXPECTED);
+
+  // kIpV6Endpoint3 fails.
+  connect_completers[2].Complete(ERR_UNEXPECTED);
+
+  // IPv4 IPs come in, and DNS completes.
+  request->set_endpoints({service_endpoint})
+      .CallOnServiceEndpointRequestFinished(OK);
+
+  // Both connectors now try IPv4 IPs. Use a similar completion pattern as
+  // before, though flipping the order so the first one fails first, and failing
+  // with ERR_UNEXPECTED before ERR_FAILED. Again, each Connector should try two
+  // IPs. One IP succeeds, this time.
+  connect_completers[4].WaitForConnect();
+  connect_completers[5].WaitForConnect();
+
+  connect_completers[4].Complete(ERR_UNEXPECTED);
+  connect_completers[6].WaitForConnect();
+
+  connect_completers[5].Complete(ERR_UNEXPECTED);
+  connect_completers[7].WaitForConnectAndComplete(ERR_FAILED);
+
+  connect_completers[6].Complete(OK);
+
+  WaitForSuccess(kIpV4Endpoint3, service_endpoint,
+                 /*expected_connection_attempts=*/
+                 {{kIpV6Endpoint2, ERR_FAILED},
+                  {kIpV6Endpoint1, ERR_FAILED},
+                  {kIpV6Endpoint4, ERR_UNEXPECTED},
+                  {kIpV6Endpoint3, ERR_UNEXPECTED},
+                  {kIpV4Endpoint1, ERR_UNEXPECTED},
+                  {kIpV4Endpoint2, ERR_UNEXPECTED},
+                  {kIpV4Endpoint4, ERR_FAILED}});
+  // No more time should have passed since the slow job was started, since time
+  // wasn't simulated advancing, and there should have been no other timed delay
+  // by TcpConnectJob.
+  EXPECT_EQ(base::Time::Now() - start_time, TcpConnectJob::kIPv6FallbackTime);
+}
+
+// Test the case where there are two Connectors with multiple service endpoints,
+// all received at once. Each ServiceEndpoint should only be tried after all IPs
+// from the previous endpoint have failed. In this test, the primary job only
+// tries IPv6 IPs and the IPv4 job only tries IPv4 jobs, just to keep things
+// simple.
+TEST_F(TcpConnectJobTest, TwoConnectorsMultipleServiceEndpoints) {
+  const auto service_endpoint1 =
+      CreateServiceEndpoint({kIpV6Endpoint1, kIpV6Endpoint2, kIpV4Endpoint1});
+  // This shared kIpV6Endpoint2 with `service_endpoint1`, but it should not be
+  // retried.
+  const auto service_endpoint2 = CreateServiceEndpoint(
+      {kIpV6Endpoint2, kIpV6Endpoint3, kIpV4Endpoint2, kIpV4Endpoint3});
+  // This shared kIpV6Endpoint2 and kIpV4Endpoint2 with earlier
+  // ServiceEndpoints, but neither should be retried.
+  const auto service_endpoint3 = CreateServiceEndpoint(
+      {kIpV6Endpoint2, kIpV6Endpoint4, kIpV4Endpoint2, kIpV4Endpoint4});
+
+  base::Time start_time = base::Time::Now();
+
+  host_resolver_.ConfigureDefaultResolution()
+      .set_endpoints({service_endpoint1, service_endpoint2, service_endpoint3})
+      .CompleteStartSynchronously(OK);
+
+  std::array<MockConnectCompleter, 8> connect_completers;
+  AddConnect(MockConnect(&connect_completers[0]), kIpV6Endpoint1);
+  AddConnect(MockConnect(&connect_completers[1]), kIpV4Endpoint1);
+  AddConnect(MockConnect(&connect_completers[2]), kIpV6Endpoint2);
+  AddConnect(MockConnect(&connect_completers[3]), kIpV4Endpoint2);
+  AddConnect(MockConnect(&connect_completers[4]), kIpV6Endpoint3);
+  AddConnect(MockConnect(&connect_completers[5]), kIpV4Endpoint3);
+  AddConnect(MockConnect(&connect_completers[6]), kIpV6Endpoint4);
+  AddConnect(MockConnect(&connect_completers[7]), kIpV4Endpoint4);
+
+  EXPECT_THAT(InitAndStart(), IsError(ERR_IO_PENDING));
+
+  connect_completers[0].WaitForConnect();
+  EXPECT_FALSE(connect_job_->has_two_connectors_for_testing());
+  EXPECT_EQ(base::Time::Now() - start_time, base::TimeDelta());
+
+  // Wait for the second Connector to start, which should mean the fallback time
+  // has passed.
+  connect_completers[1].WaitForConnect();
+  EXPECT_TRUE(connect_job_->has_two_connectors_for_testing());
+  EXPECT_EQ(base::Time::Now() - start_time, TcpConnectJob::kIPv6FallbackTime);
+
+  // kIpV6Endpoint1 and kIpV6Endpoint2 fail. The primary Connector should sit
+  // idle, waiting for the last IP from `service_endpoint1` to complete.
+  connect_completers[0].Complete(ERR_FAILED);
+  connect_completers[2].WaitForConnectAndComplete(ERR_FAILED);
+  // Spin message loop, to run any pending task(s).
+  FastForwardBy(base::Seconds(1));
+  // There should be no pending connection attempt to the next two IPs.
+  EXPECT_FALSE(connect_completers[3].is_connecting());
+  EXPECT_FALSE(connect_completers[4].is_connecting());
+
+  // Fail the final IP in `service_endpoint1`. This should cause us to start on
+  // `service_endpoint2`.
+  connect_completers[1].Complete(ERR_UNEXPECTED);
+
+  // The IPv4 job gets next IP, first, since it had the last failure, and the
+  // task to wake up the other Connector is posted asynchronously.
+  connect_completers[3].WaitForConnect();
+  EXPECT_FALSE(connect_completers[4].is_connecting());
+  connect_completers[4].WaitForConnect();
+
+  // kIpV4Endpoint2 and kIpV4Endpoint3 fail. Connecting to the final two IPs
+  // from `service_endpoint3` should be blocked by the connection attempt to
+  // kIpV6Endpoint3, by the primary Connector.
+  connect_completers[3].Complete(ERR_FAILED);
+  connect_completers[5].WaitForConnectAndComplete(ERR_FAILED);
+  // Spin message loop, to run any pending task(s).
+  FastForwardBy(base::Seconds(1));
+  // There should be no pending connection attempt to the next two IPs.
+  EXPECT_FALSE(connect_completers[6].is_connecting());
+  EXPECT_FALSE(connect_completers[7].is_connecting());
+
+  // Fail the final IP in `service_endpoint2`. This should cause us to start on
+  // `service_endpoint3`.
+  connect_completers[4].Complete(ERR_UNEXPECTED);
+
+  // The primary job gets next IP, first, since it had the last failure, and the
+  // task to wake up the other Connector is posted asynchronously.
+  connect_completers[6].WaitForConnect();
+  EXPECT_FALSE(connect_completers[7].is_connecting());
+  connect_completers[7].WaitForConnect();
+
+  // Complete the last two IPs. The connection attempt to kIpV4Endpoint4
+  // succeeds.
+  connect_completers[6].Complete(ERR_FAILED);
+  connect_completers[7].Complete(OK);
+
+  WaitForSuccess(kIpV4Endpoint4, service_endpoint3,
+                 /*expected_connection_attempts=*/
+                 {{kIpV6Endpoint1, ERR_FAILED},
+                  {kIpV6Endpoint2, ERR_FAILED},
+                  {kIpV4Endpoint1, ERR_UNEXPECTED},
+                  {kIpV4Endpoint2, ERR_FAILED},
+                  {kIpV4Endpoint3, ERR_FAILED},
+                  {kIpV6Endpoint3, ERR_UNEXPECTED},
+                  {kIpV6Endpoint4, ERR_FAILED}});
+}
+
+// Test the with two Connectors where the endpoint index goes backwards. This is
+// a pretty unusual situation, since generally A/AAAA will complete first, and
+// the maximum index will be 0, until the HTTPS record completes, but that could
+// change in the future, and it should work.
+TEST_F(TcpConnectJobTest, TwoConnectorsEndpointIndexBackwards) {
+  // This test will start with only endpoints 3 and 4. Then, after the IP in 3
+  // fails, and we're connecting to the first two endpoints in
+  // `service_endpoint4`, the DNS resolution completes, proving all endpoints.
+  // Then as soon as either of the endpoints in 4 fails, we start with the
+  // endpoints in `service_endpoint1`, and then work our way back down to 4
+  // again (which would have been the second in the ServiceEndpoints list,
+  // initially).
+  //
+  // This test also covers the case where `primary_connector` is connecting to
+  // an IPv4 IP when we make the second connector, so it should become the IPv4
+  // Connector when we make a second one.
+  const auto service_endpoint1 = CreateServiceEndpoint(
+      {kIpV6Endpoint1, kIpV4Endpoint1, kIpV6Endpoint3, kIpV4Endpoint4});
+  const auto service_endpoint2 =
+      CreateServiceEndpoint({kIpV6Endpoint2, kIpV4Endpoint2, kIpV4Endpoint3});
+  const auto service_endpoint3 = CreateServiceEndpoint({kIpV6Endpoint3});
+  const auto service_endpoint4 =
+      CreateServiceEndpoint({kIpV4Endpoint3, kIpV6Endpoint4, kIpV4Endpoint4,
+                             kIpV6Endpoint1, kIpV4Endpoint2});
+
+  base::Time start_time = base::Time::Now();
+
+  auto request = host_resolver_.AddFakeRequest();
+
+  std::array<MockConnectCompleter, 8> connect_completers;
+  AddConnect(MockConnect(&connect_completers[0]), kIpV6Endpoint3);
+  AddConnect(MockConnect(&connect_completers[1]), kIpV4Endpoint3);
+  AddConnect(MockConnect(&connect_completers[2]), kIpV6Endpoint4);
+  AddConnect(MockConnect(&connect_completers[3]), kIpV4Endpoint1);
+  AddConnect(MockConnect(&connect_completers[4]), kIpV6Endpoint1);
+  AddConnect(MockConnect(&connect_completers[5]), kIpV4Endpoint4);
+  AddConnect(MockConnect(&connect_completers[6]), kIpV4Endpoint2);
+  AddConnect(MockConnect(&connect_completers[7]), kIpV6Endpoint2);
+
+  EXPECT_THAT(InitAndStart(), IsError(ERR_IO_PENDING));
+
+  // Crypto ready shouldn't actually matter here, but set it, just to make sure
+  // it does not.
+  request->set_crypto_ready(true)
+      .set_endpoints({service_endpoint3, service_endpoint4})
+      .CallOnServiceEndpointsUpdated();
+
+  // Fail the only IP in `service_endpoint3` (kIpV6Endpoint3) and move on to the
+  // first IPv4 IP in `service_endpoint4`.
+  connect_completers[0].WaitForConnectAndComplete(ERR_FAILED);
+  connect_completers[1].WaitForConnect();
+  EXPECT_FALSE(connect_job_->has_two_connectors_for_testing());
+  EXPECT_EQ(base::Time::Now() - start_time, base::TimeDelta());
+
+  // Wait for the second Connector to start, which should mean the fallback time
+  // has passed.
+  connect_completers[2].WaitForConnect();
+  EXPECT_TRUE(connect_job_->has_two_connectors_for_testing());
+  EXPECT_EQ(base::Time::Now() - start_time, TcpConnectJob::kIPv6FallbackTime);
+
+  // DNS request completes, with two more ServiceEndpoints.
+  request
+      ->set_endpoints({service_endpoint1, service_endpoint2, service_endpoint3,
+                       service_endpoint4})
+      .CallOnServiceEndpointRequestFinished(OK);
+
+  // kIpV4Endpoint3 fails. The IPv4 job should attempt to connect to
+  // kIpV4Endpoint1, from `service_endpoint1`.
+  connect_completers[1].Complete(ERR_FAILED);
+  connect_completers[3].WaitForConnect();
+
+  // kIpV6Endpoint4 fails, the primary job should attempt to connect to
+  // kIpV6Endpoint1, which also fails, and then to connect to kIpV4Endpoint4,
+  // since kIpV6Endpoint3 has already been tried. That also fails.
+  connect_completers[2].Complete(ERR_FAILED);
+  connect_completers[4].WaitForConnectAndComplete(ERR_FAILED);
+  connect_completers[5].WaitForConnectAndComplete(ERR_FAILED);
+
+  // Spin message loop, to run any pending task(s). There should be no new
+  // connection attempt, yet, since we're still working on `service_endpoint1`.
+  FastForwardBy(base::Seconds(1));
+  EXPECT_FALSE(connect_completers[6].is_connecting());
+
+  // kIpV4Endpoint1 fails, which is the last IP in `service_endpoint1`.
+  connect_completers[3].Complete(ERR_FAILED);
+
+  // We try to connect to last two IPs. IPv4 one is first, since it's the IPv4
+  // job that had the last failed connection attempt, but that isn't too
+  // important.
+  connect_completers[6].WaitForConnect();
+  connect_completers[7].WaitForConnect();
+
+  // Fail both of those. There should be no more attempts, since every IP has
+  // been tried.
+  connect_completers[6].Complete(ERR_FAILED);
+  connect_completers[7].Complete(ERR_FAILED);
+
+  WaitForError(ERR_FAILED,
+               /*expected_connection_attempts=*/
+               {{kIpV6Endpoint3, ERR_FAILED},
+                {kIpV4Endpoint3, ERR_FAILED},
+                {kIpV6Endpoint4, ERR_FAILED},
+                {kIpV6Endpoint1, ERR_FAILED},
+                {kIpV4Endpoint4, ERR_FAILED},
+                {kIpV4Endpoint1, ERR_FAILED},
+                {kIpV4Endpoint2, ERR_FAILED},
+                {kIpV6Endpoint2, ERR_FAILED}});
+}
+
 }  // namespace
 }  // namespace net
diff --git a/pdf/paint_manager.cc b/pdf/paint_manager.cc
index dd42c06..2948f4c 100644
--- a/pdf/paint_manager.cc
+++ b/pdf/paint_manager.cc
@@ -138,6 +138,8 @@
 
   if (base::FeatureList::IsEnabled(features::kPdfBufferedPaintManager)) {
     gfx::Size new_new_size = GetNewContextSize(plugin_size_, new_size);
+    static_assert(SkColorType::kN32_SkColorType ==
+                  SkColorType::kBGRA_8888_SkColorType);
     image_info_ = SkImageInfo::MakeN32(new_new_size.width(),
                                        new_new_size.height(), alpha_type);
     plugin_size_ = new_size;
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index 06425ee1..e993056 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -609,6 +609,22 @@
 
 #endif
 
+void CheckBitmapProperties(const SkBitmap& sk_bitmap, FPDF_BITMAP fpdf_bitmap) {
+  CHECK_EQ(sk_bitmap.colorType(), SkColorType::kBGRA_8888_SkColorType);
+  switch (FPDFBitmap_GetFormat(fpdf_bitmap)) {
+    case FPDFBitmap_BGRA_Premul:
+      CHECK_EQ(sk_bitmap.alphaType(), SkAlphaType::kPremul_SkAlphaType);
+      break;
+    case FPDFBitmap_BGRA:
+      CHECK_EQ(sk_bitmap.alphaType(), SkAlphaType::kUnpremul_SkAlphaType);
+      break;
+    case FPDFBitmap_BGRx:
+      break;  // Any alphaType is okay as long as the colorType is good
+    default:
+      NOTREACHED();
+  }
+}
+
 }  // namespace
 
 void InitializeSDK(bool enable_v8,
@@ -3556,7 +3572,13 @@
   CHECK(PageIndexInBounds(paint.page_index()));
   FPDF_PAGE page = pages_[paint.page_index()]->GetPage();
   if (paint.bitmap()) {
-    return FPDF_RenderPage_Continue(page, this) != FPDF_RENDER_TOBECONTINUED;
+    if (FPDF_RenderPage_Continue(page, this) == FPDF_RENDER_TOBECONTINUED) {
+      // Don't CheckBitmapProperties() because pdfium converts unpremul to
+      // premul in the middle stages of rendering in skia mode.
+      return false;
+    }
+    CheckBitmapProperties(image_data, paint.bitmap());
+    return true;
   }
 
   const gfx::Rect& dirty = paint.rect();
@@ -3574,11 +3596,17 @@
   FPDFBitmap_FillRect(new_bitmap_ptr, pdfium_rect.x(), pdfium_rect.y(),
                       pdfium_rect.width(), pdfium_rect.height(), fill_color);
 
-  return FPDF_RenderPageBitmap_Start(
-             new_bitmap_ptr, page, pdfium_rect.x(), pdfium_rect.y(),
-             pdfium_rect.width(), pdfium_rect.height(),
-             GetClockwiseRotationSteps(GetCurrentOrientation()),
-             GetRenderingFlags(), this) != FPDF_RENDER_TOBECONTINUED;
+  if (FPDF_RenderPageBitmap_Start(
+          new_bitmap_ptr, page, pdfium_rect.x(), pdfium_rect.y(),
+          pdfium_rect.width(), pdfium_rect.height(),
+          GetClockwiseRotationSteps(GetCurrentOrientation()),
+          GetRenderingFlags(), this) == FPDF_RENDER_TOBECONTINUED) {
+    // Don't CheckBitmapProperties() because pdfium converts unpremul to
+    // premul in the middle stages of rendering in skia mode.
+    return false;
+  }
+  CheckBitmapProperties(image_data, paint.bitmap());
+  return true;
 }
 
 void PDFiumEngine::FinishPaint(size_t progressive_index, SkBitmap& image_data) {
@@ -3606,6 +3634,7 @@
   form_highlights_.clear();
 
   FPDF_RenderPage_Close(pages_[page_index]->GetPage());
+  CheckBitmapProperties(image_data, bitmap);
   progressive_paints_.erase(progressive_paints_.begin() + progressive_index);
 
   MaybeRequestPendingThumbnail(page_index);
@@ -5243,6 +5272,7 @@
 void PDFiumEngine::ProgressivePaint::SetBitmapAndImageData(
     ScopedFPDFBitmap bitmap,
     SkBitmap image_data) {
+  CheckBitmapProperties(image_data, bitmap.get());
   bitmap_ = std::move(bitmap);
   image_data_ = std::move(image_data);
 }
diff --git a/remoting/codec/audio_encoder_opus.cc b/remoting/codec/audio_encoder_opus.cc
index 345105e..1167daa 100644
--- a/remoting/codec/audio_encoder_opus.cc
+++ b/remoting/codec/audio_encoder_opus.cc
@@ -4,12 +4,16 @@
 
 #include "remoting/codec/audio_encoder_opus.h"
 
+#include <memory>
+
 #include "base/compiler_specific.h"
 #include "base/functional/bind.h"
 #include "base/logging.h"
+#include "base/numerics/safe_math.h"
 #include "base/time/time.h"
 #include "media/base/audio_bus.h"
 #include "media/base/audio_sample_types.h"
+#include "media/base/audio_timestamp_helper.h"
 #include "media/base/multi_channel_resampler.h"
 #include "third_party/opus/src/include/opus.h"
 
@@ -18,37 +22,31 @@
 namespace {
 
 // Output 160 kb/s bitrate.
-const int kOutputBitrateBps = 160 * 1024;
+constexpr int kOutputBitrateBps = 160 * 1024;
 
 // Opus doesn't support 44100 sampling rate so we always resample to 48kHz.
-const AudioPacket::SamplingRate kOpusSamplingRate =
+constexpr AudioPacket::SamplingRate kOpusSamplingRate =
     AudioPacket::SAMPLING_RATE_48000;
 
 // Opus supports frame sizes of 2.5, 5, 10, 20, 40 and 60 ms. We use 20 ms
 // frames to balance latency and efficiency.
-const int kFrameSizeMs = 20;
+constexpr base::TimeDelta kFrameDuration = base::Milliseconds(20);
 
-// Number of samples per frame when using default sampling rate.
-const int kFrameSamples =
-    kOpusSamplingRate * kFrameSizeMs / base::Time::kMillisecondsPerSecond;
+// Number of audio frames per "opus frame" when using default sampling rate.
+constexpr size_t kOpusFrameCount = kOpusSamplingRate *
+                                   kFrameDuration.InMilliseconds() /
+                                   base::Time::kMillisecondsPerSecond;
 
-const AudioPacket::BytesPerSample kBytesPerSample =
+constexpr AudioPacket::BytesPerSample kBytesPerSample =
     AudioPacket::BYTES_PER_SAMPLE_2;
 
-bool IsSupportedSampleRate(int rate) {
+constexpr bool IsSupportedSampleRate(int rate) {
   return rate == 44100 || rate == 48000;
 }
 
 }  // namespace
 
-AudioEncoderOpus::AudioEncoderOpus()
-    : sampling_rate_(0),
-      channels_(AudioPacket::CHANNELS_STEREO),
-      encoder_(nullptr),
-      frame_size_(0),
-      resampling_data_(nullptr),
-      resampling_data_size_(0),
-      resampling_data_pos_(0) {}
+AudioEncoderOpus::AudioEncoderOpus() = default;
 
 AudioEncoderOpus::~AudioEncoderOpus() {
   DestroyEncoder();
@@ -67,11 +65,13 @@
   opus_encoder_ctl(encoder_.get(), OPUS_SET_BITRATE(kOutputBitrateBps));
 
   frame_size_ =
-      sampling_rate_ * kFrameSizeMs / base::Time::kMillisecondsPerSecond;
+      media::AudioTimestampHelper::TimeToFrames(kFrameDuration, sampling_rate_);
 
   if (sampling_rate_ != kOpusSamplingRate) {
-    resample_buffer_.reset(
-        new char[kFrameSamples * kBytesPerSample * channels_]);
+    size_t total_samples =
+        base::CheckMul(kOpusFrameCount, channels_).ValueOrDie<size_t>();
+    resample_buffer_ = base::AlignedUninit<int16_t>(
+        total_samples, media::AudioBus::kChannelAlignment);
     // TODO(sergeyu): Figure out the right buffer size to use per packet instead
     // of using media::SincResampler::kDefaultRequestSize.
     resampler_ = std::make_unique<media::MultiChannelResampler>(
@@ -79,14 +79,15 @@
         media::SincResampler::kDefaultRequestSize,
         base::BindRepeating(&AudioEncoderOpus::FetchBytesToResample,
                             base::Unretained(this)));
-    resampler_bus_ = media::AudioBus::Create(channels_, kFrameSamples);
+    resampler_bus_ = media::AudioBus::Create(channels_, kOpusFrameCount);
   }
 
   // Drop leftover data because it's for different sampling rate.
-  leftover_samples_ = 0;
-  leftover_buffer_size_ =
+  leftover_frames_ = 0;
+  leftover_samples_size_in_frames_ =
       frame_size_ + media::SincResampler::kDefaultRequestSize;
-  leftover_buffer_.reset(new int16_t[leftover_buffer_size_ * channels_]);
+  leftover_samples_.reset(
+      new int16_t[leftover_samples_size_in_frames_ * channels_]);
 }
 
 void AudioEncoderOpus::DestroyEncoder() {
@@ -150,59 +151,59 @@
     return nullptr;
   }
 
-  int samples_in_packet = packet->data(0).size() / kBytesPerSample / channels_;
+  int frames_in_packet = packet->data(0).size() / kBytesPerSample / channels_;
   const int16_t* next_sample =
       UNSAFE_TODO(reinterpret_cast<const int16_t*>(packet->data(0).data()));
 
   // Create a new packet of encoded data.
-  std::unique_ptr<AudioPacket> encoded_packet(new AudioPacket());
+  auto encoded_packet = std::make_unique<AudioPacket>();
   encoded_packet->set_encoding(AudioPacket::ENCODING_OPUS);
   encoded_packet->set_sampling_rate(kOpusSamplingRate);
   encoded_packet->set_channels(channels_);
 
-  int prefetch_samples =
+  const int prefetch_frames =
       resampler_.get() ? media::SincResampler::kDefaultRequestSize : 0;
-  int samples_wanted = frame_size_ + prefetch_samples;
+  int frames_wanted = frame_size_ + prefetch_frames;
 
-  while (leftover_samples_ + samples_in_packet >= samples_wanted) {
+  while (leftover_frames_ + frames_in_packet >= frames_wanted) {
     const int16_t* pcm_buffer = nullptr;
 
     // Combine the packet with the leftover samples, if any.
-    if (leftover_samples_ > 0) {
-      pcm_buffer = leftover_buffer_.get();
-      int samples_to_copy = samples_wanted - leftover_samples_;
-      UNSAFE_TODO(memcpy(leftover_buffer_.get() + leftover_samples_ * channels_,
+    if (leftover_frames_ > 0) {
+      pcm_buffer = leftover_samples_.get();
+      const int frames_to_copy = frames_wanted - leftover_frames_;
+      UNSAFE_TODO(memcpy(leftover_samples_.get() + leftover_frames_ * channels_,
                          next_sample,
-                         samples_to_copy * kBytesPerSample * channels_));
+                         frames_to_copy * kBytesPerSample * channels_));
     } else {
       pcm_buffer = next_sample;
     }
 
     // Resample data if necessary.
-    int samples_consumed = 0;
+    int frames_consumed = 0;
     if (resampler_.get()) {
       resampling_data_ = reinterpret_cast<const char*>(pcm_buffer);
       resampling_data_pos_ = 0;
-      resampling_data_size_ = samples_wanted * channels_ * kBytesPerSample;
-      resampler_->Resample(kFrameSamples, resampler_bus_.get());
+      resampling_data_size_ = frames_wanted * channels_ * kBytesPerSample;
+      resampler_->Resample(kOpusFrameCount, resampler_bus_.get());
       resampling_data_ = nullptr;
-      samples_consumed = resampling_data_pos_ / channels_ / kBytesPerSample;
+      frames_consumed = resampling_data_pos_ / channels_ / kBytesPerSample;
 
       static_assert(kBytesPerSample == 2, "ToInterleaved expects 2 bytes.");
       resampler_bus_->ToInterleaved<media::SignedInt16SampleTypeTraits>(
-          kFrameSamples, reinterpret_cast<int16_t*>(resample_buffer_.get()));
-      pcm_buffer = reinterpret_cast<int16_t*>(resample_buffer_.get());
+          resample_buffer_);
+      pcm_buffer = resample_buffer_.data();
     } else {
-      samples_consumed = frame_size_;
+      frames_consumed = frame_size_;
     }
 
     // Initialize output buffer.
     std::string* data = encoded_packet->add_data();
-    data->resize(kFrameSamples * kBytesPerSample * channels_);
+    data->resize(kOpusFrameCount * kBytesPerSample * channels_);
 
     // Encode.
     unsigned char* buffer = reinterpret_cast<unsigned char*>(std::data(*data));
-    int result = opus_encode(encoder_, pcm_buffer, kFrameSamples, buffer,
+    int result = opus_encode(encoder_, pcm_buffer, kOpusFrameCount, buffer,
                              data->length());
     if (result < 0) {
       LOG(ERROR) << "opus_encode() failed with error code: " << result;
@@ -213,26 +214,27 @@
     data->resize(result);
 
     // Cleanup leftover buffer.
-    if (samples_consumed >= leftover_samples_) {
-      samples_consumed -= leftover_samples_;
-      leftover_samples_ = 0;
-      UNSAFE_TODO(next_sample += samples_consumed * channels_);
-      samples_in_packet -= samples_consumed;
+    if (frames_consumed >= leftover_frames_) {
+      frames_consumed -= leftover_frames_;
+      leftover_frames_ = 0;
+      UNSAFE_TODO(next_sample += frames_consumed * channels_);
+      frames_in_packet -= frames_consumed;
     } else {
-      leftover_samples_ -= samples_consumed;
-      UNSAFE_TODO(memmove(leftover_buffer_.get(),
-                          leftover_buffer_.get() + samples_consumed * channels_,
-                          leftover_samples_ * channels_ * kBytesPerSample));
+      leftover_frames_ -= frames_consumed;
+      UNSAFE_TODO(memmove(leftover_samples_.get(),
+                          leftover_samples_.get() + frames_consumed * channels_,
+                          leftover_frames_ * channels_ * kBytesPerSample));
     }
   }
 
   // Store the leftover samples.
-  if (samples_in_packet > 0) {
-    DCHECK_LE(leftover_samples_ + samples_in_packet, leftover_buffer_size_);
-    UNSAFE_TODO(memmove(leftover_buffer_.get() + leftover_samples_ * channels_,
+  if (frames_in_packet > 0) {
+    DCHECK_LE(leftover_frames_ + frames_in_packet,
+              leftover_samples_size_in_frames_);
+    UNSAFE_TODO(memmove(leftover_samples_.get() + leftover_frames_ * channels_,
                         next_sample,
-                        samples_in_packet * kBytesPerSample * channels_));
-    leftover_samples_ += samples_in_packet;
+                        frames_in_packet * kBytesPerSample * channels_));
+    leftover_frames_ += frames_in_packet;
   }
 
   // Return nullptr if there's nothing in the packet.
diff --git a/remoting/codec/audio_encoder_opus.h b/remoting/codec/audio_encoder_opus.h
index a4dcf407..b048334 100644
--- a/remoting/codec/audio_encoder_opus.h
+++ b/remoting/codec/audio_encoder_opus.h
@@ -5,11 +5,9 @@
 #ifndef REMOTING_CODEC_AUDIO_ENCODER_OPUS_H_
 #define REMOTING_CODEC_AUDIO_ENCODER_OPUS_H_
 
+#include "base/memory/aligned_memory.h"
 #include "base/memory/raw_ptr.h"
 #include "remoting/codec/audio_encoder.h"
-
-#include <stdint.h>
-
 #include "remoting/proto/audio.pb.h"
 
 struct OpusEncoder;
@@ -45,24 +43,24 @@
   void FetchBytesToResample(int resampler_frame_delay,
                             media::AudioBus* audio_bus);
 
-  int sampling_rate_;
-  AudioPacket::Channels channels_;
-  raw_ptr<OpusEncoder, DanglingUntriaged> encoder_;
+  int sampling_rate_ = 0;
+  AudioPacket::Channels channels_ = AudioPacket::CHANNELS_STEREO;
+  raw_ptr<OpusEncoder, DanglingUntriaged> encoder_ = nullptr;
 
-  int frame_size_;
+  int frame_size_ = 0;
   std::unique_ptr<media::MultiChannelResampler> resampler_;
-  std::unique_ptr<char[]> resample_buffer_;
+  base::AlignedHeapArray<int16_t> resample_buffer_;
   std::unique_ptr<media::AudioBus> resampler_bus_;
 
   // Used to pass packet to the FetchBytesToResampler() callback.
-  const char* resampling_data_;
-  int resampling_data_size_;
-  int resampling_data_pos_;
+  const char* resampling_data_ = nullptr;
+  int resampling_data_size_ = 0;
+  int resampling_data_pos_ = 0;
 
   // Left-over unencoded samples from the previous AudioPacket.
-  std::unique_ptr<int16_t[]> leftover_buffer_;
-  int leftover_buffer_size_;
-  int leftover_samples_;
+  std::unique_ptr<int16_t[]> leftover_samples_;
+  int leftover_samples_size_in_frames_ = 0;
+  int leftover_frames_ = 0;
 };
 
 }  // namespace remoting
diff --git a/remoting/protocol/BUILD.gn b/remoting/protocol/BUILD.gn
index 4556697..4daab165 100644
--- a/remoting/protocol/BUILD.gn
+++ b/remoting/protocol/BUILD.gn
@@ -371,7 +371,6 @@
     "//remoting/codec:encoder",
     "//remoting/signaling",
     "//testing/gtest",
-    "//third_party/libjingle_xmpp:rtc_xmllite",
   ]
 }
 
@@ -451,7 +450,6 @@
     "//services/network/public/cpp",
     "//testing/gmock",
     "//testing/gtest",
-    "//third_party/libjingle_xmpp:rtc_xmllite",
     "//third_party/webrtc_overrides:webrtc_component",
   ]
 
diff --git a/remoting/protocol/authenticator.cc b/remoting/protocol/authenticator.cc
index 3c1844fe..3495f435 100644
--- a/remoting/protocol/authenticator.cc
+++ b/remoting/protocol/authenticator.cc
@@ -7,15 +7,9 @@
 #include "base/functional/bind.h"
 #include "base/logging.h"
 #include "remoting/base/constants.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
-namespace {
-const jingle_xmpp::StaticQName kAuthenticationQName = {kChromotingXmlNamespace,
-                                                       "authentication"};
-}  // namespace
-
 Authenticator::RejectionDetails::RejectionDetails() = default;
 Authenticator::RejectionDetails::RejectionDetails(RejectionDetails&&) = default;
 Authenticator::RejectionDetails::RejectionDetails(const RejectionDetails&) =
@@ -36,24 +30,6 @@
 Authenticator::Authenticator() = default;
 Authenticator::~Authenticator() = default;
 
-// static
-bool Authenticator::IsAuthenticatorMessage(
-    const jingle_xmpp::XmlElement* message) {
-  return message->Name() == kAuthenticationQName;
-}
-
-// static
-std::unique_ptr<jingle_xmpp::XmlElement>
-Authenticator::CreateEmptyAuthenticatorMessage() {
-  return std::make_unique<jingle_xmpp::XmlElement>(kAuthenticationQName);
-}
-
-// static
-const jingle_xmpp::XmlElement* Authenticator::FindAuthenticatorMessage(
-    const jingle_xmpp::XmlElement* message) {
-  return message->FirstNamed(kAuthenticationQName);
-}
-
 void Authenticator::NotifyStateChangeAfterAccepted() {
   if (on_state_change_after_accepted_) {
     on_state_change_after_accepted_.Run();
diff --git a/remoting/protocol/authenticator.h b/remoting/protocol/authenticator.h
index 9827e89..340fdc9 100644
--- a/remoting/protocol/authenticator.h
+++ b/remoting/protocol/authenticator.h
@@ -15,10 +15,6 @@
 #include "remoting/protocol/credentials_type.h"
 #include "remoting/signaling/jingle_data_structures.h"
 
-namespace jingle_xmpp {
-class XmlElement;
-}  // namespace jingle_xmpp
-
 namespace remoting::protocol {
 
 class Authenticator;
@@ -155,18 +151,6 @@
       Authenticator::State initial_state)>
       CreateBaseAuthenticatorCallback;
 
-  // Returns true if |message| is an Authenticator message.
-  static bool IsAuthenticatorMessage(const jingle_xmpp::XmlElement* message);
-
-  // Creates an empty Authenticator message, owned by the caller.
-  static std::unique_ptr<jingle_xmpp::XmlElement>
-  CreateEmptyAuthenticatorMessage();
-
-  // Finds Authenticator message among child elements of |message|, or
-  // returns nullptr otherwise.
-  static const jingle_xmpp::XmlElement* FindAuthenticatorMessage(
-      const jingle_xmpp::XmlElement* message);
-
   Authenticator();
   virtual ~Authenticator();
 
diff --git a/remoting/protocol/authenticator_test_base.cc b/remoting/protocol/authenticator_test_base.cc
index d37102a..d0423f5 100644
--- a/remoting/protocol/authenticator_test_base.cc
+++ b/remoting/protocol/authenticator_test_base.cc
@@ -22,7 +22,6 @@
 #include "remoting/protocol/fake_stream_socket.h"
 #include "remoting/protocol/p2p_stream_socket.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 using testing::_;
 using testing::SaveArg;
diff --git a/remoting/protocol/fake_authenticator.cc b/remoting/protocol/fake_authenticator.cc
index 678ba16..3e31e57ab 100644
--- a/remoting/protocol/fake_authenticator.cc
+++ b/remoting/protocol/fake_authenticator.cc
@@ -18,7 +18,6 @@
 #include "remoting/protocol/authenticator.h"
 #include "remoting/protocol/p2p_stream_socket.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/fake_session.cc b/remoting/protocol/fake_session.cc
index 151fef5..4fff67b 100644
--- a/remoting/protocol/fake_session.cc
+++ b/remoting/protocol/fake_session.cc
@@ -15,7 +15,6 @@
 #include "remoting/protocol/fake_authenticator.h"
 #include "remoting/protocol/session_plugin.h"
 #include "remoting/signaling/jingle_message_xml_converter.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
@@ -139,27 +138,6 @@
   }
 }
 
-void FakeSession::SetAttachment(
-    size_t round,
-    std::unique_ptr<jingle_xmpp::XmlElement> attachment) {
-  if (!attachment) {
-    return;
-  }
-
-  Attachment attachment_struct;
-  if (AttachmentFromXml(attachment.get(), &attachment_struct)) {
-    SetAttachment(round, attachment_struct);
-  } else {
-    // Try wrapping it in an <attachments> element.
-    jingle_xmpp::XmlElement wrapper(
-        jingle_xmpp::QName(kChromotingXmlNamespace, "attachments"));
-    wrapper.AddElement(new jingle_xmpp::XmlElement(*attachment));
-    if (AttachmentFromXml(&wrapper, &attachment_struct)) {
-      SetAttachment(round, attachment_struct);
-    }
-  }
-}
-
 void FakeSession::SetAttachment(size_t round, const Attachment& attachment) {
   if (attachments_.size() <= round) {
     attachments_.resize(round + 1);
diff --git a/remoting/protocol/fake_session.h b/remoting/protocol/fake_session.h
index db17d65..adbc3e58 100644
--- a/remoting/protocol/fake_session.h
+++ b/remoting/protocol/fake_session.h
@@ -50,8 +50,6 @@
 
   // Adds an |attachment| to |round|, which will be sent to plugins added by
   // AddPlugin() function.
-  void SetAttachment(size_t round,
-                     std::unique_ptr<jingle_xmpp::XmlElement> attachment);
   void SetAttachment(size_t round, const Attachment& attachment);
 
   // Session interface.
diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc
index ec85c263..42841ce 100644
--- a/remoting/protocol/jingle_session.cc
+++ b/remoting/protocol/jingle_session.cc
@@ -37,11 +37,8 @@
 #include "remoting/signaling/jingle_message_xml_converter.h"
 #include "remoting/signaling/session_config.h"
 #include "remoting/signaling/xmpp_constants.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 #include "third_party/webrtc/api/candidate.h"
 
-using jingle_xmpp::XmlElement;
-
 namespace remoting::protocol {
 
 namespace {
@@ -507,7 +504,7 @@
 
 void JingleSession::OnMessageResponse(JingleMessage::ActionType request_type,
                                       IqRequest* request,
-                                      const jingle_xmpp::XmlElement* response) {
+                                      const JingleMessageReply& response) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   // Delete the request from the list of pending requests.
@@ -521,22 +518,18 @@
 
   std::string type_str = JingleMessage::GetActionName(request_type);
 
-  // |response| will be nullptr if the request timed out.
-  if (!response) {
-    Close(ErrorCode::SIGNALING_TIMEOUT,
-          base::StringPrintf("%s request timed out.", type_str), FROM_HERE);
-    return;
-  } else {
-    const std::string& type =
-        response->Attr(jingle_xmpp::QName(std::string(), "type"));
-    if (type != "result") {
+  if (response.type != JingleMessageReply::REPLY_RESULT) {
+    if (response.text == "timeout") {
+      Close(ErrorCode::SIGNALING_TIMEOUT,
+            base::StringPrintf("%s request timed out.", type_str), FROM_HERE);
+    } else {
       // TODO(sergeyu): There may be different reasons for error
       // here. Parse the response stanza to find failure reason.
       Close(ErrorCode::PEER_IS_OFFLINE,
             base::StringPrintf(
                 "Received error in response to %s message: \"%s\". "
                 "Terminating the session.",
-                type_str, response->Str()),
+                type_str, response.text.c_str()),
             FROM_HERE);
     }
   }
@@ -544,7 +537,7 @@
 
 void JingleSession::OnTransportInfoResponse(
     IqRequest* request,
-    const jingle_xmpp::XmlElement* response) {
+    const JingleMessageReply& response) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(!transport_info_requests_.empty());
 
@@ -556,21 +549,17 @@
   transport_info_requests_.erase(transport_info_requests_.begin(),
                                  request_it + 1);
 
-  // Ignore transport-info timeouts.
-  if (!response) {
-    LOG(ERROR) << "transport-info request has timed out.";
-    return;
-  }
-
-  const std::string& type =
-      response->Attr(jingle_xmpp::QName(std::string(), "type"));
-  if (type != "result") {
-    Close(ErrorCode::PEER_IS_OFFLINE,
-          base::StringPrintf(
-              "Received error in response to transport-info message: \"%s\". "
-              "Terminating the session.",
-              response->Str()),
-          FROM_HERE);
+  if (response.type != JingleMessageReply::REPLY_RESULT) {
+    if (response.text == "timeout") {
+      LOG(ERROR) << "transport-info request has timed out.";
+    } else {
+      Close(ErrorCode::PEER_IS_OFFLINE,
+            base::StringPrintf(
+                "Received error in response to transport-info message: \"%s\". "
+                "Terminating the session.",
+                response.text.c_str()),
+            FROM_HERE);
+    }
   }
 }
 
@@ -596,7 +585,7 @@
 
   if (peer_address_ != message->from) {
     // Ignore messages received from a different Jid.
-    std::move(reply_callback).Run(JingleMessageReply::INVALID_SID);
+    std::move(reply_callback).Run(*message, JingleMessageReply::INVALID_SID);
     return;
   }
 
@@ -620,18 +609,20 @@
       break;
 
     default:
-      std::move(reply_callback).Run(JingleMessageReply::UNEXPECTED_REQUEST);
+      std::move(reply_callback)
+          .Run(*message, JingleMessageReply::UNEXPECTED_REQUEST);
   }
 }
 
 void JingleSession::OnAccept(std::unique_ptr<JingleMessage> message,
                              ReplyCallback reply_callback) {
   if (state_ != CONNECTING) {
-    std::move(reply_callback).Run(JingleMessageReply::UNEXPECTED_REQUEST);
+    std::move(reply_callback)
+        .Run(*message, JingleMessageReply::UNEXPECTED_REQUEST);
     return;
   }
 
-  std::move(reply_callback).Run(JingleMessageReply::NONE);
+  std::move(reply_callback).Run(*message, JingleMessageReply::NONE);
 
   const JingleAuthentication& auth_message =
       message->description->authentication();
@@ -668,19 +659,21 @@
   }
 
   if (!auth_message) {
-    std::move(reply_callback).Run(JingleMessageReply::UNSUPPORTED_INFO);
+    std::move(reply_callback)
+        .Run(*message, JingleMessageReply::UNSUPPORTED_INFO);
     return;
   }
 
   if ((state_ != ACCEPTED && state_ != AUTHENTICATING) ||
       authenticator_->state() != Authenticator::WAITING_MESSAGE) {
-    std::move(reply_callback).Run(JingleMessageReply::UNEXPECTED_REQUEST);
+    std::move(reply_callback)
+        .Run(*message, JingleMessageReply::UNEXPECTED_REQUEST);
     Close(ErrorCode::INVALID_ARGUMENT,
           "Received unexpected authenticator message", FROM_HERE);
     return;
   }
 
-  std::move(reply_callback).Run(JingleMessageReply::NONE);
+  std::move(reply_callback).Run(*message, JingleMessageReply::NONE);
 
   authenticator_->ProcessMessage(
       *auth_message, base::BindOnce(&JingleSession::ProcessAuthenticationStep,
@@ -690,7 +683,7 @@
 void JingleSession::OnTransportInfo(std::unique_ptr<JingleMessage> message,
                                     ReplyCallback reply_callback) {
   if (!std::holds_alternative<JingleTransportInfo>(message->payload())) {
-    std::move(reply_callback).Run(JingleMessageReply::BAD_REQUEST);
+    std::move(reply_callback).Run(*message, JingleMessageReply::BAD_REQUEST);
     return;
   }
 
@@ -699,13 +692,14 @@
         PendingMessage{std::move(message), std::move(reply_callback)});
   } else if (state_ == AUTHENTICATED) {
     std::move(reply_callback)
-        .Run(transport_->ProcessTransportInfo(
-                 std::get<JingleTransportInfo>(message->payload()))
-                 ? JingleMessageReply::NONE
-                 : JingleMessageReply::BAD_REQUEST);
+        .Run(*message, transport_->ProcessTransportInfo(
+                           std::get<JingleTransportInfo>(message->payload()))
+                           ? JingleMessageReply::NONE
+                           : JingleMessageReply::BAD_REQUEST);
   } else {
     LOG(ERROR) << "Received unexpected transport-info message.";
-    std::move(reply_callback).Run(JingleMessageReply::UNEXPECTED_REQUEST);
+    std::move(reply_callback)
+        .Run(*message, JingleMessageReply::UNEXPECTED_REQUEST);
   }
 }
 
@@ -713,11 +707,12 @@
                                 ReplyCallback reply_callback) {
   if (!is_session_active()) {
     LOG(WARNING) << "Received unexpected session-terminate message.";
-    std::move(reply_callback).Run(JingleMessageReply::UNEXPECTED_REQUEST);
+    std::move(reply_callback)
+        .Run(*message, JingleMessageReply::UNEXPECTED_REQUEST);
     return;
   }
 
-  std::move(reply_callback).Run(JingleMessageReply::NONE);
+  std::move(reply_callback).Run(*message, JingleMessageReply::NONE);
 
   error_ = message->error_code;
   if (error_ == ErrorCode::UNKNOWN_ERROR) {
@@ -855,7 +850,8 @@
   std::swap(messages_to_process, pending_transport_info_);
   for (auto& message : messages_to_process) {
     std::move(message.reply_callback)
-        .Run(transport_->ProcessTransportInfo(
+        .Run(*message.message,
+             transport_->ProcessTransportInfo(
                  std::get<JingleTransportInfo>(message.message->payload()))
                  ? JingleMessageReply::NONE
                  : JingleMessageReply::BAD_REQUEST);
diff --git a/remoting/protocol/jingle_session.h b/remoting/protocol/jingle_session.h
index 2ce11d6..a127a4c 100644
--- a/remoting/protocol/jingle_session.h
+++ b/remoting/protocol/jingle_session.h
@@ -54,7 +54,8 @@
  private:
   friend class JingleSessionManager;
 
-  using ReplyCallback = base::OnceCallback<void(JingleMessageReply::ErrorType)>;
+  using ReplyCallback = base::OnceCallback<void(const JingleMessage&,
+                                                JingleMessageReply::ErrorType)>;
 
   explicit JingleSession(JingleSessionManager* session_manager);
 
@@ -79,12 +80,12 @@
   // Iq response handler.
   void OnMessageResponse(JingleMessage::ActionType request_type,
                          IqRequest* request,
-                         const jingle_xmpp::XmlElement* response);
+                         const JingleMessageReply& response);
 
   // Response handler for transport-info responses. Transport-info timeouts are
   // ignored and don't terminate connection.
   void OnTransportInfoResponse(IqRequest* request,
-                               const jingle_xmpp::XmlElement* response);
+                               const JingleMessageReply& response);
 
   // Called by JingleSessionManager on incoming |message|. Must call
   // |reply_callback| to send reply message before sending any other
diff --git a/remoting/protocol/jingle_session_manager.cc b/remoting/protocol/jingle_session_manager.cc
index c2dccc5..b09c1529 100644
--- a/remoting/protocol/jingle_session_manager.cc
+++ b/remoting/protocol/jingle_session_manager.cc
@@ -19,11 +19,8 @@
 #include "remoting/signaling/jingle_message_xml_converter.h"
 #include "remoting/signaling/signal_strategy.h"
 #include "remoting/signaling/xmpp_constants.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 #include "third_party/webrtc/rtc_base/socket_address.h"
 
-using jingle_xmpp::QName;
-
 namespace remoting::protocol {
 
 JingleSessionManager::JingleSessionManager(SignalStrategy* signal_strategy)
@@ -80,17 +77,13 @@
 bool JingleSessionManager::OnSignalStrategyIncomingMessage(
     const SignalingAddress& sender_address,
     const SignalingMessage& signaling_message) {
-  // TODO: joedow - Update JingleSessionManager to use JingleMessage.
-  auto stanza = SignalStrategy::GetXmlStanza(signaling_message);
-  if (!stanza || !IsJingleMessage(stanza.get())) {
-    return false;
-  }
-
   auto message = std::make_unique<JingleMessage>();
   std::string error_msg;
-  if (!JingleMessageFromXml(stanza.get(), message.get(), &error_msg)) {
-    SendReply(std::move(stanza), JingleMessageReply::BAD_REQUEST);
-    return true;
+  std::unique_ptr<jingle_xmpp::XmlElement> stanza =
+      SignalStrategy::GetXmlStanza(signaling_message);
+  if (!stanza || !IsJingleMessage(stanza.get()) ||
+      !JingleMessageFromXml(stanza.get(), message.get(), &error_msg)) {
+    return false;
   }
 
   // TODO: joedow - Use std::visit(absl::Overload(...),
@@ -100,8 +93,7 @@
     // Description must be present in session-initiate messages.
     DCHECK(message->description.get());
 
-    SendReply(std::make_unique<jingle_xmpp::XmlElement>(*stanza),
-              JingleMessageReply::NONE);
+    SendReply(*message, JingleMessageReply::NONE);
 
     std::unique_ptr<Authenticator> authenticator =
         authenticator_factory_->CreateAuthenticator(
@@ -153,20 +145,20 @@
 
   auto it = sessions_.find(message->sid);
   if (it == sessions_.end()) {
-    SendReply(std::move(stanza), JingleMessageReply::INVALID_SID);
+    SendReply(*message, JingleMessageReply::INVALID_SID);
     return true;
   }
 
   it->second->OnIncomingMessage(
       std::move(message),
-      base::BindOnce(&JingleSessionManager::SendReply, base::Unretained(this),
-                     std::move(stanza)));
+      base::BindOnce(&JingleSessionManager::SendReply, base::Unretained(this)));
   return true;
 }
 
-void JingleSessionManager::SendReply(
-    std::unique_ptr<jingle_xmpp::XmlElement> original_stanza,
-    JingleMessageReply::ErrorType error) {
+void JingleSessionManager::SendReply(const JingleMessage& original_message,
+                                     JingleMessageReply::ErrorType error) {
+  std::unique_ptr<jingle_xmpp::XmlElement> original_stanza =
+      JingleMessageToXml(original_message);
   std::unique_ptr<jingle_xmpp::XmlElement> reply_stanza =
       JingleMessageReplyToXml(JingleMessageReply(error), original_stanza.get());
   SignalingAddress to =
diff --git a/remoting/protocol/jingle_session_manager.h b/remoting/protocol/jingle_session_manager.h
index 6e86ef10..2baded69 100644
--- a/remoting/protocol/jingle_session_manager.h
+++ b/remoting/protocol/jingle_session_manager.h
@@ -17,10 +17,6 @@
 #include "remoting/signaling/jingle_data_structures.h"
 #include "remoting/signaling/signal_strategy.h"
 
-namespace jingle_xmpp {
-class XmlElement;
-}  // namespace jingle_xmpp
-
 namespace remoting {
 
 class IqSender;
@@ -71,7 +67,7 @@
       SessionsMap;
 
   IqSender* iq_sender() { return iq_sender_.get(); }
-  void SendReply(std::unique_ptr<jingle_xmpp::XmlElement> original_stanza,
+  void SendReply(const JingleMessage& original_message,
                  JingleMessageReply::ErrorType error);
 
   // Called by JingleSession when it is being destroyed.
diff --git a/remoting/protocol/jingle_session_unittest.cc b/remoting/protocol/jingle_session_unittest.cc
index 4d25213..eac72cafd 100644
--- a/remoting/protocol/jingle_session_unittest.cc
+++ b/remoting/protocol/jingle_session_unittest.cc
@@ -398,14 +398,12 @@
 
   // Verify that the client specified correct initiator value.
   ASSERT_GT(host_signal_strategy_->received_messages().size(), 0U);
-  const jingle_xmpp::XmlElement* initiate_xml =
-      host_signal_strategy_->received_messages().front().get();
-  const jingle_xmpp::XmlElement* jingle_element = initiate_xml->FirstNamed(
-      jingle_xmpp::QName("urn:xmpp:jingle:1", "jingle"));
-  ASSERT_TRUE(jingle_element);
-  ASSERT_EQ(
-      client_signal_strategy_->GetLocalAddress().id(),
-      jingle_element->Attr(jingle_xmpp::QName(std::string(), "initiator")));
+  JingleMessage message;
+  std::string error;
+  ASSERT_TRUE(JingleMessageFromXml(
+      host_signal_strategy_->received_messages().front().get(), &message,
+      &error));
+  ASSERT_EQ(client_signal_strategy_->GetLocalAddress().id(), message.initiator);
 }
 
 // Verify that we can connect two endpoints with multi-step authentication.
diff --git a/remoting/protocol/me2me_host_authenticator_factory.cc b/remoting/protocol/me2me_host_authenticator_factory.cc
index bbf6265..3d289a60 100644
--- a/remoting/protocol/me2me_host_authenticator_factory.cc
+++ b/remoting/protocol/me2me_host_authenticator_factory.cc
@@ -20,7 +20,6 @@
 #include "remoting/protocol/rejecting_authenticator.h"
 #include "remoting/signaling/signaling_address.h"
 #include "remoting/signaling/signaling_id_util.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/negotiating_authenticator_base.cc b/remoting/protocol/negotiating_authenticator_base.cc
index 86816f8..897723fd 100644
--- a/remoting/protocol/negotiating_authenticator_base.cc
+++ b/remoting/protocol/negotiating_authenticator_base.cc
@@ -17,7 +17,6 @@
 #include "remoting/protocol/authenticator.h"
 #include "remoting/protocol/channel_authenticator.h"
 #include "remoting/protocol/credentials_type.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/negotiating_authenticator_unittest.cc b/remoting/protocol/negotiating_authenticator_unittest.cc
index c0398994..7ef4220c 100644
--- a/remoting/protocol/negotiating_authenticator_unittest.cc
+++ b/remoting/protocol/negotiating_authenticator_unittest.cc
@@ -25,7 +25,6 @@
 #include "remoting/protocol/protocol_mock_objects.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 using testing::_;
 using testing::DeleteArg;
diff --git a/remoting/protocol/negotiating_client_authenticator.cc b/remoting/protocol/negotiating_client_authenticator.cc
index 83f6c28..24606d7 100644
--- a/remoting/protocol/negotiating_client_authenticator.cc
+++ b/remoting/protocol/negotiating_client_authenticator.cc
@@ -21,7 +21,6 @@
 #include "remoting/protocol/host_authentication_config.h"
 #include "remoting/protocol/pairing_client_authenticator.h"
 #include "remoting/protocol/spake2_authenticator.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/negotiating_host_authenticator.cc b/remoting/protocol/negotiating_host_authenticator.cc
index a189f271..746ceb2 100644
--- a/remoting/protocol/negotiating_host_authenticator.cc
+++ b/remoting/protocol/negotiating_host_authenticator.cc
@@ -23,7 +23,6 @@
 #include "remoting/protocol/pairing_registry.h"
 #include "remoting/protocol/session_authz_authenticator.h"
 #include "remoting/protocol/spake2_authenticator.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/pairing_authenticator_base.h b/remoting/protocol/pairing_authenticator_base.h
index 7f3eab6..3278fc1 100644
--- a/remoting/protocol/pairing_authenticator_base.h
+++ b/remoting/protocol/pairing_authenticator_base.h
@@ -7,7 +7,6 @@
 
 #include "base/memory/weak_ptr.h"
 #include "remoting/protocol/authenticator.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/pairing_client_authenticator.cc b/remoting/protocol/pairing_client_authenticator.cc
index d07160fa..13d4936 100644
--- a/remoting/protocol/pairing_client_authenticator.cc
+++ b/remoting/protocol/pairing_client_authenticator.cc
@@ -9,7 +9,6 @@
 #include "remoting/base/constants.h"
 #include "remoting/protocol/auth_util.h"
 #include "remoting/protocol/channel_authenticator.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/pairing_host_authenticator.cc b/remoting/protocol/pairing_host_authenticator.cc
index d0197a3..ccb38040 100644
--- a/remoting/protocol/pairing_host_authenticator.cc
+++ b/remoting/protocol/pairing_host_authenticator.cc
@@ -10,7 +10,6 @@
 #include "base/logging.h"
 #include "remoting/base/constants.h"
 #include "remoting/protocol/channel_authenticator.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/protocol_mock_objects.h b/remoting/protocol/protocol_mock_objects.h
index 37e035f..32870299 100644
--- a/remoting/protocol/protocol_mock_objects.h
+++ b/remoting/protocol/protocol_mock_objects.h
@@ -36,7 +36,6 @@
 #include "remoting/protocol/video_stub.h"
 #include "remoting/signaling/signaling_address.h"
 #include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/rejecting_authenticator.cc b/remoting/protocol/rejecting_authenticator.cc
index ceeadd54..dd1634c 100644
--- a/remoting/protocol/rejecting_authenticator.cc
+++ b/remoting/protocol/rejecting_authenticator.cc
@@ -8,7 +8,6 @@
 #include "base/functional/callback.h"
 #include "base/notreached.h"
 #include "remoting/protocol/channel_authenticator.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/session_authz_authenticator.h b/remoting/protocol/session_authz_authenticator.h
index 55b75374..42b39a3 100644
--- a/remoting/protocol/session_authz_authenticator.h
+++ b/remoting/protocol/session_authz_authenticator.h
@@ -21,7 +21,6 @@
 #include "remoting/protocol/channel_authenticator.h"
 #include "remoting/protocol/credentials_type.h"
 #include "remoting/protocol/session_authz_reauthorizer.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/spake2_authenticator.cc b/remoting/protocol/spake2_authenticator.cc
index 1974b847..1ef17efe 100644
--- a/remoting/protocol/spake2_authenticator.cc
+++ b/remoting/protocol/spake2_authenticator.cc
@@ -20,7 +20,6 @@
 #include "remoting/protocol/authenticator.h"
 #include "remoting/protocol/ssl_hmac_channel_authenticator.h"
 #include "third_party/boringssl/src/include/openssl/curve25519.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/spake2_authenticator_unittest.cc b/remoting/protocol/spake2_authenticator_unittest.cc
index 2b75194..cafe76b 100644
--- a/remoting/protocol/spake2_authenticator_unittest.cc
+++ b/remoting/protocol/spake2_authenticator_unittest.cc
@@ -13,7 +13,6 @@
 #include "remoting/protocol/connection_tester.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 using testing::_;
 using testing::DeleteArg;
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc b/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc
index 926c224..3b2e2d1 100644
--- a/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc
+++ b/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc
@@ -25,7 +25,6 @@
 #include "remoting/protocol/p2p_stream_socket.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 using testing::_;
 using testing::NotNull;
diff --git a/remoting/protocol/validating_authenticator.cc b/remoting/protocol/validating_authenticator.cc
index 58b1028..cf33e0b 100644
--- a/remoting/protocol/validating_authenticator.cc
+++ b/remoting/protocol/validating_authenticator.cc
@@ -16,7 +16,6 @@
 #include "base/memory/weak_ptr.h"
 #include "remoting/protocol/authenticator.h"
 #include "remoting/protocol/channel_authenticator.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/validating_authenticator_unittest.cc b/remoting/protocol/validating_authenticator_unittest.cc
index 2c19615d..f88555b 100644
--- a/remoting/protocol/validating_authenticator_unittest.cc
+++ b/remoting/protocol/validating_authenticator_unittest.cc
@@ -21,7 +21,6 @@
 #include "remoting/protocol/protocol_mock_objects.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting::protocol {
 
diff --git a/remoting/protocol/webrtc_transport_unittest.cc b/remoting/protocol/webrtc_transport_unittest.cc
index b9c0d84..f3a07e3 100644
--- a/remoting/protocol/webrtc_transport_unittest.cc
+++ b/remoting/protocol/webrtc_transport_unittest.cc
@@ -33,7 +33,6 @@
 #include "remoting/signaling/jingle_data_structures.h"
 #include "remoting/signaling/jingle_message_xml_converter.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 #include "third_party/webrtc/api/scoped_refptr.h"
 
 namespace remoting::protocol {
@@ -192,20 +191,6 @@
       bool normalize_line_endings,
       std::unique_ptr<JingleTransportInfo> transport_info) {
     ASSERT_TRUE(target_transport);
-
-    // Reformat the message to normalize line endings by removing CR symbol.
-    if (normalize_line_endings) {
-      std::unique_ptr<jingle_xmpp::XmlElement> xml =
-          JingleTransportInfoToXml(*transport_info);
-      std::string xml_str = xml->Str();
-      base::ReplaceChars(xml_str, "\r", std::string(), &xml_str);
-      std::unique_ptr<jingle_xmpp::XmlElement> normalized_xml(
-          jingle_xmpp::XmlElement::ForStr(xml_str));
-      transport_info = std::make_unique<JingleTransportInfo>();
-      EXPECT_TRUE(JingleTransportInfoFromXml(normalized_xml.get(),
-                                             transport_info.get()));
-    }
-
     EXPECT_TRUE((*target_transport)->ProcessTransportInfo(*transport_info));
   }
 
diff --git a/remoting/signaling/iq_sender.cc b/remoting/signaling/iq_sender.cc
index 90306b77..8df5feab 100644
--- a/remoting/signaling/iq_sender.cc
+++ b/remoting/signaling/iq_sender.cc
@@ -120,7 +120,12 @@
   }
 
   requests_.erase(it);
-  request->OnResponse(stanza.get());
+  JingleMessageReply reply;
+  if (!JingleMessageReplyFromXml(stanza.get(), &reply)) {
+    LOG(WARNING) << "Failed to parse IQ response " << stanza->Str();
+    return false;
+  }
+  request->OnResponse(reply);
 
   return true;
 }
@@ -141,30 +146,30 @@
       timeout);
 }
 
-void IqRequest::CallCallback(const jingle_xmpp::XmlElement* stanza) {
+void IqRequest::CallCallback(const JingleMessageReply& reply) {
   if (!callback_.is_null()) {
-    std::move(callback_).Run(this, stanza);
+    std::move(callback_).Run(this, reply);
   }
 }
 
 void IqRequest::OnTimeout() {
-  CallCallback(nullptr);
+  JingleMessageReply reply;
+  reply.type = JingleMessageReply::REPLY_ERROR;
+  reply.error_type = JingleMessageReply::UNEXPECTED_REQUEST;
+  reply.text = "timeout";
+  CallCallback(reply);
 }
 
-void IqRequest::OnResponse(const jingle_xmpp::XmlElement* stanza) {
+void IqRequest::OnResponse(const JingleMessageReply& reply) {
   // It's unsafe to delete signal strategy here, and the callback may
   // want to do that, so we post task to invoke the callback later.
-  std::unique_ptr<jingle_xmpp::XmlElement> stanza_copy(
-      new jingle_xmpp::XmlElement(*stanza));
   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&IqRequest::DeliverResponse, weak_factory_.GetWeakPtr(),
-                     std::move(stanza_copy)));
+      FROM_HERE, base::BindOnce(&IqRequest::DeliverResponse,
+                                weak_factory_.GetWeakPtr(), reply));
 }
 
-void IqRequest::DeliverResponse(
-    std::unique_ptr<jingle_xmpp::XmlElement> stanza) {
-  CallCallback(stanza.get());
+void IqRequest::DeliverResponse(const JingleMessageReply& reply) {
+  CallCallback(reply);
 }
 
 }  // namespace remoting
diff --git a/remoting/signaling/iq_sender.h b/remoting/signaling/iq_sender.h
index ab592b3..963bf21 100644
--- a/remoting/signaling/iq_sender.h
+++ b/remoting/signaling/iq_sender.h
@@ -27,17 +27,17 @@
 
 class IqRequest;
 class JingleMessage;
+struct JingleMessageReply;
 class SignalStrategy;
 
 // IqSender handles sending iq requests and routing of responses to
 // those requests.
 class IqSender : public SignalStrategy::Listener {
  public:
-  // Callback that is called when an Iq response is received. Called
-  // with the |response| set to nullptr in case of a timeout.
+  // Callback that is called when an Iq response is received.
   using ReplyCallback =
       base::OnceCallback<void(IqRequest* request,
-                              const jingle_xmpp::XmlElement* response)>;
+                              const JingleMessageReply& response)>;
 
   explicit IqSender(SignalStrategy* signal_strategy);
 
@@ -96,13 +96,13 @@
  private:
   friend class IqSender;
 
-  void CallCallback(const jingle_xmpp::XmlElement* stanza);
+  void CallCallback(const JingleMessageReply& reply);
   void OnTimeout();
 
   // Called by IqSender when a response is received.
-  void OnResponse(const jingle_xmpp::XmlElement* stanza);
+  void OnResponse(const JingleMessageReply& reply);
 
-  void DeliverResponse(std::unique_ptr<jingle_xmpp::XmlElement> stanza);
+  void DeliverResponse(const JingleMessageReply& reply);
 
   raw_ptr<IqSender> sender_;
   IqSender::ReplyCallback callback_;
diff --git a/remoting/signaling/iq_sender_unittest.cc b/remoting/signaling/iq_sender_unittest.cc
index 4f798c4..7cf424db 100644
--- a/remoting/signaling/iq_sender_unittest.cc
+++ b/remoting/signaling/iq_sender_unittest.cc
@@ -39,8 +39,9 @@
 const char kStanzaId[] = "123";
 const char kTo[] = "user@domain.com";
 
-MATCHER_P(XmlEq, expected, "") {
-  return arg->Str() == expected->Str();
+MATCHER_P(ReplyEq, expected, "") {
+  return arg.type == expected.type && arg.error_type == expected.error_type &&
+         arg.text == expected.text;
 }
 
 }  // namespace
@@ -112,10 +113,13 @@
 TEST_F(IqSenderTest, SendIq) {
   ASSERT_NO_FATAL_FAILURE({ SendTestMessage(); });
 
-  std::unique_ptr<XmlElement> response;
-  EXPECT_TRUE(FormatAndDeliverResponse(kTo, &response));
+  std::unique_ptr<XmlElement> response_xml;
+  EXPECT_TRUE(FormatAndDeliverResponse(kTo, &response_xml));
 
-  EXPECT_CALL(callback_, Run(request_.get(), XmlEq(response.get())));
+  JingleMessageReply expected_reply;
+  ASSERT_TRUE(JingleMessageReplyFromXml(response_xml.get(), &expected_reply));
+
+  EXPECT_CALL(callback_, Run(request_.get(), ReplyEq(expected_reply)));
   base::RunLoop().RunUntilIdle();
 }
 
@@ -124,8 +128,13 @@
 
   request_->SetTimeout(base::Milliseconds(2));
 
+  JingleMessageReply expected_reply;
+  expected_reply.type = JingleMessageReply::REPLY_ERROR;
+  expected_reply.error_type = JingleMessageReply::UNEXPECTED_REQUEST;
+  expected_reply.text = "timeout";
+
   base::RunLoop run_loop;
-  EXPECT_CALL(callback_, Run(request_.get(), nullptr))
+  EXPECT_CALL(callback_, Run(request_.get(), ReplyEq(expected_reply)))
       .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::QuitWhenIdle));
   run_loop.Run();
 }
@@ -135,10 +144,13 @@
 
   // Set upper-case from value, which is equivalent to kTo in the original
   // message.
-  std::unique_ptr<XmlElement> response;
-  EXPECT_TRUE(FormatAndDeliverResponse("USER@domain.com", &response));
+  std::unique_ptr<XmlElement> response_xml;
+  EXPECT_TRUE(FormatAndDeliverResponse("USER@domain.com", &response_xml));
 
-  EXPECT_CALL(callback_, Run(request_.get(), XmlEq(response.get())));
+  JingleMessageReply expected_reply;
+  ASSERT_TRUE(JingleMessageReplyFromXml(response_xml.get(), &expected_reply));
+
+  EXPECT_CALL(callback_, Run(request_.get(), ReplyEq(expected_reply)));
   base::RunLoop().RunUntilIdle();
 }
 
diff --git a/remoting/signaling/jingle_message_xml_converter.cc b/remoting/signaling/jingle_message_xml_converter.cc
index 9607dc71..1b241ade 100644
--- a/remoting/signaling/jingle_message_xml_converter.cc
+++ b/remoting/signaling/jingle_message_xml_converter.cc
@@ -683,6 +683,54 @@
   return iq;
 }
 
+bool JingleMessageReplyFromXml(const jingle_xmpp::XmlElement* stanza,
+                               JingleMessageReply* reply) {
+  if (stanza->Name() != kQNameIq) {
+    return false;
+  }
+
+  const std::string& type = stanza->Attr(kQNameType);
+  if (type == "result") {
+    reply->type = JingleMessageReply::REPLY_RESULT;
+    reply->error_type = JingleMessageReply::NONE;
+    return true;
+  }
+
+  if (type != "error") {
+    return false;
+  }
+
+  reply->type = JingleMessageReply::REPLY_ERROR;
+
+  const XmlElement* error_tag =
+      stanza->FirstNamed(QName(kJabberNamespace, "error"));
+  if (error_tag) {
+    if (error_tag->FirstNamed(QName(kJabberNamespace, "bad-request"))) {
+      reply->error_type = JingleMessageReply::BAD_REQUEST;
+    } else if (error_tag->FirstNamed(
+                   QName(kJabberNamespace, "feature-bad-request"))) {
+      reply->error_type = JingleMessageReply::NOT_IMPLEMENTED;
+    } else if (error_tag->FirstNamed(
+                   QName(kJabberNamespace, "item-not-found"))) {
+      reply->error_type = JingleMessageReply::INVALID_SID;
+    } else if (error_tag->FirstNamed(
+                   QName(kJabberNamespace, "unexpected-request"))) {
+      reply->error_type = JingleMessageReply::UNEXPECTED_REQUEST;
+    } else if (error_tag->FirstNamed(
+                   QName(kJabberNamespace, "feature-not-implemented"))) {
+      reply->error_type = JingleMessageReply::UNSUPPORTED_INFO;
+    }
+
+    const XmlElement* text_tag =
+        error_tag->FirstNamed(QName(kJabberNamespace, "text"));
+    if (text_tag) {
+      reply->text = text_tag->BodyText();
+    }
+  }
+
+  return true;
+}
+
 bool IsJingleMessage(const jingle_xmpp::XmlElement* stanza) {
   return stanza->Name() == kQNameIq && stanza->Attr(kQNameType) == "set" &&
          stanza->FirstNamed(kQNameJingle) != nullptr;
diff --git a/remoting/signaling/jingle_message_xml_converter.h b/remoting/signaling/jingle_message_xml_converter.h
index fc8d147..35ae3c3 100644
--- a/remoting/signaling/jingle_message_xml_converter.h
+++ b/remoting/signaling/jingle_message_xml_converter.h
@@ -36,6 +36,8 @@
 std::unique_ptr<jingle_xmpp::XmlElement> JingleMessageReplyToXml(
     const JingleMessageReply& reply,
     const jingle_xmpp::XmlElement* request_stanza);
+bool JingleMessageReplyFromXml(const jingle_xmpp::XmlElement* stanza,
+                               JingleMessageReply* reply);
 
 // Helper to check if an XML element represents a Jingle message.
 bool IsJingleMessage(const jingle_xmpp::XmlElement* stanza);
diff --git a/services/device/generic_sensor/android/junit/src/org/chromium/device/sensors/PlatformSensorAndProviderTest.java b/services/device/generic_sensor/android/junit/src/org/chromium/device/sensors/PlatformSensorAndProviderTest.java
index 61571d8..f656308c 100644
--- a/services/device/generic_sensor/android/junit/src/org/chromium/device/sensors/PlatformSensorAndProviderTest.java
+++ b/services/device/generic_sensor/android/junit/src/org/chromium/device/sensors/PlatformSensorAndProviderTest.java
@@ -28,11 +28,13 @@
 import android.util.SparseArray;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.mockito.stubbing.Answer;
 import org.robolectric.annotation.Config;
 
@@ -93,9 +95,10 @@
         protected void sensorError() {}
     }
 
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         // Remove all mock sensors before the test.
         mMockSensors.clear();
         doReturn(mSensorManager).when(mContext).getSystemService(Context.SENSOR_SERVICE);
diff --git a/services/device/geolocation/android/junit/src/org/chromium/device/geolocation/LocationProviderTest.java b/services/device/geolocation/android/junit/src/org/chromium/device/geolocation/LocationProviderTest.java
index 2583d90..7ad5b30 100644
--- a/services/device/geolocation/android/junit/src/org/chromium/device/geolocation/LocationProviderTest.java
+++ b/services/device/geolocation/android/junit/src/org/chromium/device/geolocation/LocationProviderTest.java
@@ -29,13 +29,13 @@
 import com.google.android.gms.location.LocationRequest;
 import com.google.android.gms.tasks.Tasks;
 
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.ParameterizedRobolectricTestRunner;
 import org.robolectric.ParameterizedRobolectricTestRunner.Parameters;
 import org.robolectric.annotation.Config;
@@ -83,10 +83,7 @@
         mApi = api;
     }
 
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-    }
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
 
     /** Verify a normal start/stop call pair with the given LocationProvider. */
     @Test
diff --git a/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java b/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java
index d243067..afdb012d 100644
--- a/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java
+++ b/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java
@@ -32,12 +32,14 @@
 import android.os.Bundle;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.ApiCompatibilityUtils;
@@ -125,9 +127,10 @@
         public void stopTrackingActivityForHost(int hostId) {}
     }
 
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mDelegate = new TestNfcDelegate(mActivity);
         doReturn(mNfcManager).when(mContext).getSystemService(Context.NFC_SERVICE);
         doReturn(mNfcAdapter).when(mNfcManager).getDefaultAdapter();
diff --git a/services/shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java b/services/shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java
index 5718df7..5fb7199 100644
--- a/services/shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java
+++ b/services/shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java
@@ -6,10 +6,11 @@
 
 import static org.junit.Assert.assertNull;
 
-import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -30,10 +31,7 @@
 
     public BitmapUtilsTest() {}
 
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-    }
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
 
     /** Verify conversion fails if the Bitmap is invalid. */
     @Test
diff --git a/services/webnn/dml/tensor_impl_dml.h b/services/webnn/dml/tensor_impl_dml.h
index f40c7e1..6b050b4 100644
--- a/services/webnn/dml/tensor_impl_dml.h
+++ b/services/webnn/dml/tensor_impl_dml.h
@@ -63,6 +63,10 @@
   // access to WebNN and to EndAccessWebNN() again.
   scoped_refptr<gfx::D3DSharedFence> EndAccessWebNN();
 
+  base::WeakPtr<const TensorImplDml> GetWeakPtr() const {
+    return weak_factory_.GetWeakPtr();
+  }
+
  private:
   ~TensorImplDml() override;
 
diff --git a/services/webnn/webnn_tensor_impl.h b/services/webnn/webnn_tensor_impl.h
index 8c561856..ee3bd56 100644
--- a/services/webnn/webnn_tensor_impl.h
+++ b/services/webnn/webnn_tensor_impl.h
@@ -48,10 +48,6 @@
   size_t PackedByteLength() const { return descriptor_.PackedByteLength(); }
   size_t NumberOfElements() const { return descriptor_.NumberOfElements(); }
 
-  base::WeakPtr<const WebNNTensorImpl> GetWeakPtr() const {
-    return weak_factory_.GetWeakPtr();
-  }
-
   bool IsValidWithDescriptor(const OperandDescriptor& descriptor) const;
 
   // This method will be called by `WriteTensor()` after the write info is
@@ -137,8 +133,6 @@
 
   const OperandDescriptor descriptor_;
   const MLTensorUsage usage_;
-
-  base::WeakPtrFactory<WebNNTensorImpl> weak_factory_{this};
 };
 
 }  // namespace webnn
diff --git a/testing/perf/cbb_ref_info/chrome/stable/android.json b/testing/perf/cbb_ref_info/chrome/stable/android.json
index 61f7d26f..bbd4c456 100644
--- a/testing/perf/cbb_ref_info/chrome/stable/android.json
+++ b/testing/perf/cbb_ref_info/chrome/stable/android.json
@@ -2,5 +2,5 @@
   "browser": "chrome",
   "channel": "stable",
   "platform": "android",
-  "version": "145.0.7632.120"
+  "version": "146.0.7680.31"
 }
\ No newline at end of file
diff --git a/testing/perf/cbb_ref_info/chrome/stable/mac.json b/testing/perf/cbb_ref_info/chrome/stable/mac.json
index 01e3c90..1968fccb 100644
--- a/testing/perf/cbb_ref_info/chrome/stable/mac.json
+++ b/testing/perf/cbb_ref_info/chrome/stable/mac.json
@@ -2,5 +2,5 @@
   "browser": "chrome",
   "channel": "stable",
   "platform": "mac",
-  "version": "145.0.7632.117"
+  "version": "146.0.7680.31"
 }
\ No newline at end of file
diff --git a/testing/perf/cbb_ref_info/chrome/stable/windows.json b/testing/perf/cbb_ref_info/chrome/stable/windows.json
index e9a0352..c9836a2e 100644
--- a/testing/perf/cbb_ref_info/chrome/stable/windows.json
+++ b/testing/perf/cbb_ref_info/chrome/stable/windows.json
@@ -2,5 +2,5 @@
   "browser": "chrome",
   "channel": "stable",
   "platform": "windows",
-  "version": "145.0.7632.117"
+  "version": "146.0.7680.31"
 }
\ No newline at end of file
diff --git a/testing/perf/cbb_ref_info/edge/dev/windows.json b/testing/perf/cbb_ref_info/edge/dev/windows.json
index 210312b..0af0ab2 100644
--- a/testing/perf/cbb_ref_info/edge/dev/windows.json
+++ b/testing/perf/cbb_ref_info/edge/dev/windows.json
@@ -2,5 +2,5 @@
   "browser": "edge",
   "channel": "dev",
   "platform": "windows",
-  "version": "146.0.3856.20"
+  "version": "147.0.3878.0"
 }
\ No newline at end of file
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 73ca0ce..121cd09 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -2504,24 +2504,6 @@
             ]
         }
     ],
-    "AutofillEnableCvcStorage": [
-        {
-            "platforms": [
-                "ios"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "AutofillEnableCvcStorageAndFilling",
-                        "AutofillEnableCvcStorageAndFillingEnhancement",
-                        "AutofillEnableCvcStorageAndFillingStandaloneFormEnhancement",
-                        "SyncAutofillWalletCredentialData"
-                    ]
-                }
-            ]
-        }
-    ],
     "AutofillEnableFillingPhoneCountryCodesByAddressCountryCodes": [
         {
             "platforms": [
@@ -17143,21 +17125,6 @@
             ]
         }
     ],
-    "NearbyMdns": [
-        {
-            "platforms": [
-                "chromeos"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "EnableNearbyMdns"
-                    ]
-                }
-            ]
-        }
-    ],
     "NearbyShareNameEnabled": [
         {
             "platforms": [
@@ -26267,6 +26234,26 @@
             ]
         }
     ],
+    "ThrottleFrameSinksOnInteractionExperiment": [
+        {
+            "platforms": [
+                "chromeos",
+                "android",
+                "android_webview",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "ThrottleFrameSinksOnInteraction"
+                    ]
+                }
+            ]
+        }
+    ],
     "ThrottleMainFrameTo60HzMacV3": [
         {
             "platforms": [
diff --git a/third_party/androidx/build.gradle b/third_party/androidx/build.gradle
index 30a81fa9..357e16d 100644
--- a/third_party/androidx/build.gradle
+++ b/third_party/androidx/build.gradle
@@ -322,7 +322,7 @@
     google()
     maven {
         // This URL is generated by the fetch_all_androidx.py script.
-        url 'https://androidx.dev/snapshots/builds/14936970/artifacts/repository'
+        url 'https://androidx.dev/snapshots/builds/14939483/artifacts/repository'
     }
     mavenCentral()
 }
diff --git a/third_party/androidx/committed/libs/androidx_activity_activity/README.chromium b/third_party/androidx/committed/libs/androidx_activity_activity/README.chromium
index d65fe06..d76f90c 100644
--- a/third_party/androidx/committed/libs/androidx_activity_activity/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_activity_activity/README.chromium
@@ -1,6 +1,6 @@
 Name: Activity
 Short Name: activity
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/activity/activity/1.13.0-SNAPSHOT/activity-1.13.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/activity/activity/1.13.0-SNAPSHOT/activity-1.13.0-20260225.210851-1.aar
 Version: 1.13.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_activity_activity_compose/README.chromium b/third_party/androidx/committed/libs/androidx_activity_activity_compose/README.chromium
index bf6ccc2..b58ac53 100644
--- a/third_party/androidx/committed/libs/androidx_activity_activity_compose/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_activity_activity_compose/README.chromium
@@ -1,6 +1,6 @@
 Name: Activity Compose
 Short Name: activity-compose
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/activity/activity-compose/1.13.0-SNAPSHOT/activity-compose-1.13.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/activity/activity-compose/1.13.0-SNAPSHOT/activity-compose-1.13.0-20260225.210851-1.aar
 Version: 1.13.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_activity_activity_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_activity_activity_ktx/README.chromium
index 9bf55ea..4dab496 100644
--- a/third_party/androidx/committed/libs/androidx_activity_activity_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_activity_activity_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: Activity Kotlin Extensions
 Short Name: activity-ktx
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/activity/activity-ktx/1.13.0-SNAPSHOT/activity-ktx-1.13.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/activity/activity-ktx/1.13.0-SNAPSHOT/activity-ktx-1.13.0-20260225.210851-1.aar
 Version: 1.13.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_annotation_annotation_experimental/README.chromium b/third_party/androidx/committed/libs/androidx_annotation_annotation_experimental/README.chromium
index 3186d29..5ce755a 100644
--- a/third_party/androidx/committed/libs/androidx_annotation_annotation_experimental/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_annotation_annotation_experimental/README.chromium
@@ -1,6 +1,6 @@
 Name: Experimental annotation
 Short Name: annotation-experimental
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/annotation/annotation-experimental/1.6.0-SNAPSHOT/annotation-experimental-1.6.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/annotation/annotation-experimental/1.6.0-SNAPSHOT/annotation-experimental-1.6.0-20260225.210851-1.aar
 Version: 1.6.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_annotation_annotation_jvm/README.chromium b/third_party/androidx/committed/libs/androidx_annotation_annotation_jvm/README.chromium
index 6314aaa2..09b461c1 100644
--- a/third_party/androidx/committed/libs/androidx_annotation_annotation_jvm/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_annotation_annotation_jvm/README.chromium
@@ -1,6 +1,6 @@
 Name: Annotation
 Short Name: annotation-jvm
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/annotation/annotation-jvm/1.10.0-SNAPSHOT/annotation-jvm-1.10.0-20260225.133501-1.jar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/annotation/annotation-jvm/1.10.0-SNAPSHOT/annotation-jvm-1.10.0-20260225.210851-1.jar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_appcompat_appcompat/README.chromium b/third_party/androidx/committed/libs/androidx_appcompat_appcompat/README.chromium
index 56c20646..57555da 100644
--- a/third_party/androidx/committed/libs/androidx_appcompat_appcompat/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_appcompat_appcompat/README.chromium
@@ -1,6 +1,6 @@
 Name: AppCompat
 Short Name: appcompat
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/appcompat/appcompat/1.8.0-SNAPSHOT/appcompat-1.8.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/appcompat/appcompat/1.8.0-SNAPSHOT/appcompat-1.8.0-20260225.210851-1.aar
 Version: 1.8.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_appcompat_appcompat_resources/README.chromium b/third_party/androidx/committed/libs/androidx_appcompat_appcompat_resources/README.chromium
index 0609d60..cb24d5a 100644
--- a/third_party/androidx/committed/libs/androidx_appcompat_appcompat_resources/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_appcompat_appcompat_resources/README.chromium
@@ -1,6 +1,6 @@
 Name: AppCompat Resources
 Short Name: appcompat-resources
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/appcompat/appcompat-resources/1.8.0-SNAPSHOT/appcompat-resources-1.8.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/appcompat/appcompat-resources/1.8.0-SNAPSHOT/appcompat-resources-1.8.0-20260225.210851-1.aar
 Version: 1.8.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_appsearch_appsearch/README.chromium b/third_party/androidx/committed/libs/androidx_appsearch_appsearch/README.chromium
index 4027945..1357bda 100644
--- a/third_party/androidx/committed/libs/androidx_appsearch_appsearch/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_appsearch_appsearch/README.chromium
@@ -1,6 +1,6 @@
 Name: AppSearch
 Short Name: appsearch
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/appsearch/appsearch/1.2.0-SNAPSHOT/appsearch-1.2.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/appsearch/appsearch/1.2.0-SNAPSHOT/appsearch-1.2.0-20260225.210851-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_appsearch_appsearch_builtin_types/README.chromium b/third_party/androidx/committed/libs/androidx_appsearch_appsearch_builtin_types/README.chromium
index 71c7773..c8805860 100644
--- a/third_party/androidx/committed/libs/androidx_appsearch_appsearch_builtin_types/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_appsearch_appsearch_builtin_types/README.chromium
@@ -1,6 +1,6 @@
 Name: AppSearch Builtin Types
 Short Name: appsearch-builtin-types
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/appsearch/appsearch-builtin-types/1.2.0-SNAPSHOT/appsearch-builtin-types-1.2.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/appsearch/appsearch-builtin-types/1.2.0-SNAPSHOT/appsearch-builtin-types-1.2.0-20260225.210851-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_appsearch_appsearch_platform_storage/README.chromium b/third_party/androidx/committed/libs/androidx_appsearch_appsearch_platform_storage/README.chromium
index b98e8200..39a3853c 100644
--- a/third_party/androidx/committed/libs/androidx_appsearch_appsearch_platform_storage/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_appsearch_appsearch_platform_storage/README.chromium
@@ -1,6 +1,6 @@
 Name: AppSearch Platform Storage
 Short Name: appsearch-platform-storage
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/appsearch/appsearch-platform-storage/1.2.0-SNAPSHOT/appsearch-platform-storage-1.2.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/appsearch/appsearch-platform-storage/1.2.0-SNAPSHOT/appsearch-platform-storage-1.2.0-20260225.210851-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_arch_core_core_common/README.chromium b/third_party/androidx/committed/libs/androidx_arch_core_core_common/README.chromium
index 52c935d..38ff7b4 100644
--- a/third_party/androidx/committed/libs/androidx_arch_core_core_common/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_arch_core_core_common/README.chromium
@@ -1,6 +1,6 @@
 Name: Arch-Common
 Short Name: core-common
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/arch/core/core-common/2.3.0-SNAPSHOT/core-common-2.3.0-20260225.133501-1.jar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/arch/core/core-common/2.3.0-SNAPSHOT/core-common-2.3.0-20260225.210851-1.jar
 Version: 2.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_arch_core_core_runtime/README.chromium b/third_party/androidx/committed/libs/androidx_arch_core_core_runtime/README.chromium
index dfda2f6..b72f3400 100644
--- a/third_party/androidx/committed/libs/androidx_arch_core_core_runtime/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_arch_core_core_runtime/README.chromium
@@ -1,6 +1,6 @@
 Name: Arch-Runtime
 Short Name: core-runtime
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/arch/core/core-runtime/2.3.0-SNAPSHOT/core-runtime-2.3.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/arch/core/core-runtime/2.3.0-SNAPSHOT/core-runtime-2.3.0-20260225.210851-1.aar
 Version: 2.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_autofill_autofill/README.chromium b/third_party/androidx/committed/libs/androidx_autofill_autofill/README.chromium
index 79af4bc..34b45fb8 100644
--- a/third_party/androidx/committed/libs/androidx_autofill_autofill/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_autofill_autofill/README.chromium
@@ -1,6 +1,6 @@
 Name: Autofill
 Short Name: autofill
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/autofill/autofill/1.4.0-SNAPSHOT/autofill-1.4.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/autofill/autofill/1.4.0-SNAPSHOT/autofill-1.4.0-20260225.210851-1.aar
 Version: 1.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_common/README.chromium b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_common/README.chromium
index 229c599..782a1ab6 100644
--- a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_common/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_common/README.chromium
@@ -1,6 +1,6 @@
 Name: Benchmark - Common
 Short Name: benchmark-common
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/benchmark/benchmark-common/1.5.0-SNAPSHOT/benchmark-common-1.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/benchmark/benchmark-common/1.5.0-SNAPSHOT/benchmark-common-1.5.0-20260225.210851-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_junit4/README.chromium b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_junit4/README.chromium
index 5c40fbf..15077d43 100644
--- a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_junit4/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_junit4/README.chromium
@@ -1,6 +1,6 @@
 Name: Benchmark - JUnit4
 Short Name: benchmark-junit4
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/benchmark/benchmark-junit4/1.5.0-SNAPSHOT/benchmark-junit4-1.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/benchmark/benchmark-junit4/1.5.0-SNAPSHOT/benchmark-junit4-1.5.0-20260225.210851-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro/README.chromium b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro/README.chromium
index 2140574a..255fbeb 100644
--- a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro/README.chromium
@@ -1,6 +1,6 @@
 Name: Benchmark - Macrobenchmark
 Short Name: benchmark-macro
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/benchmark/benchmark-macro/1.5.0-SNAPSHOT/benchmark-macro-1.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/benchmark/benchmark-macro/1.5.0-SNAPSHOT/benchmark-macro-1.5.0-20260225.210851-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro_junit4/README.chromium b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro_junit4/README.chromium
index ea319ed..b42d015 100644
--- a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro_junit4/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro_junit4/README.chromium
@@ -1,6 +1,6 @@
 Name: Benchmark - Macrobenchmark JUnit4
 Short Name: benchmark-macro-junit4
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/benchmark/benchmark-macro-junit4/1.5.0-SNAPSHOT/benchmark-macro-junit4-1.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/benchmark/benchmark-macro-junit4/1.5.0-SNAPSHOT/benchmark-macro-junit4-1.5.0-20260225.210851-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_traceprocessor_android/README.chromium b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_traceprocessor_android/README.chromium
index 911dbdc..3ac163a5 100644
--- a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_traceprocessor_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_traceprocessor_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Benchmark TraceProcessor
 Short Name: benchmark-traceprocessor-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/benchmark/benchmark-traceprocessor-android/1.5.0-SNAPSHOT/benchmark-traceprocessor-android-1.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/benchmark/benchmark-traceprocessor-android/1.5.0-SNAPSHOT/benchmark-traceprocessor-android-1.5.0-20260225.210851-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_biometric_biometric/README.chromium b/third_party/androidx/committed/libs/androidx_biometric_biometric/README.chromium
index 4f60ccc..4e900e6 100644
--- a/third_party/androidx/committed/libs/androidx_biometric_biometric/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_biometric_biometric/README.chromium
@@ -1,6 +1,6 @@
 Name: Biometric
 Short Name: biometric
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/biometric/biometric/1.4.0-SNAPSHOT/biometric-1.4.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/biometric/biometric/1.4.0-SNAPSHOT/biometric-1.4.0-20260225.210851-1.aar
 Version: 1.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_browser_browser/README.chromium b/third_party/androidx/committed/libs/androidx_browser_browser/README.chromium
index 379246d..26ebc6dd 100644
--- a/third_party/androidx/committed/libs/androidx_browser_browser/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_browser_browser/README.chromium
@@ -1,6 +1,6 @@
 Name: Browser
 Short Name: browser
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/browser/browser/1.10.0-SNAPSHOT/browser-1.10.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/browser/browser/1.10.0-SNAPSHOT/browser-1.10.0-20260225.210851-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_cardview_cardview/README.chromium b/third_party/androidx/committed/libs/androidx_cardview_cardview/README.chromium
index cab325a..a252987 100644
--- a/third_party/androidx/committed/libs/androidx_cardview_cardview/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_cardview_cardview/README.chromium
@@ -1,6 +1,6 @@
 Name: CardView
 Short Name: cardview
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/cardview/cardview/1.1.0-SNAPSHOT/cardview-1.1.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/cardview/cardview/1.1.0-SNAPSHOT/cardview-1.1.0-20260225.210851-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_collection_collection_jvm/README.chromium b/third_party/androidx/committed/libs/androidx_collection_collection_jvm/README.chromium
index 2808a9c..8d0bf2e 100644
--- a/third_party/androidx/committed/libs/androidx_collection_collection_jvm/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_collection_collection_jvm/README.chromium
@@ -1,6 +1,6 @@
 Name: collections
 Short Name: collection-jvm
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/collection/collection-jvm/1.7.0-SNAPSHOT/collection-jvm-1.7.0-20260225.133501-1.jar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/collection/collection-jvm/1.7.0-SNAPSHOT/collection-jvm-1.7.0-20260225.210851-1.jar
 Version: 1.7.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_collection_collection_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_collection_collection_ktx/README.chromium
index 799cb482..bb2ce1a1 100644
--- a/third_party/androidx/committed/libs/androidx_collection_collection_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_collection_collection_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: Collections Kotlin Extensions
 Short Name: collection-ktx
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/collection/collection-ktx/1.7.0-SNAPSHOT/collection-ktx-1.7.0-20260225.133501-1.jar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/collection/collection-ktx/1.7.0-SNAPSHOT/collection-ktx-1.7.0-20260225.210851-1.jar
 Version: 1.7.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_animation_animation_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_animation_animation_android/README.chromium
index 1448de2..fd3c39bb 100644
--- a/third_party/androidx/committed/libs/androidx_compose_animation_animation_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_animation_animation_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Animation
 Short Name: animation-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/animation/animation-android/1.11.0-SNAPSHOT/animation-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/animation/animation-android/1.11.0-SNAPSHOT/animation-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_animation_animation_core_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_animation_animation_core_android/README.chromium
index eb6d5c4..3b1d743 100644
--- a/third_party/androidx/committed/libs/androidx_compose_animation_animation_core_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_animation_animation_core_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Animation Core
 Short Name: animation-core-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/animation/animation-core-android/1.11.0-SNAPSHOT/animation-core-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/animation/animation-core-android/1.11.0-SNAPSHOT/animation-core-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_android/README.chromium
index b69c6c0f..cbce94b7 100644
--- a/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Foundation
 Short Name: foundation-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/foundation/foundation-android/1.11.0-SNAPSHOT/foundation-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/foundation/foundation-android/1.11.0-SNAPSHOT/foundation-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_layout_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_layout_android/README.chromium
index 8a216c1..695d1dd1a7 100644
--- a/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_layout_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_layout_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Layouts
 Short Name: foundation-layout-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/foundation/foundation-layout-android/1.11.0-SNAPSHOT/foundation-layout-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/foundation/foundation-layout-android/1.11.0-SNAPSHOT/foundation-layout-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_material3_material3_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_material3_material3_android/README.chromium
index 55c1509..57519b05 100644
--- a/third_party/androidx/committed/libs/androidx_compose_material3_material3_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_material3_material3_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Material3 Components
 Short Name: material3-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/material3/material3-android/1.5.0-SNAPSHOT/material3-android-1.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/material3/material3-android/1.5.0-SNAPSHOT/material3-android-1.5.0-20260225.210851-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_material_material_ripple_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_material_material_ripple_android/README.chromium
index f8f3023..b4296ce 100644
--- a/third_party/androidx/committed/libs/androidx_compose_material_material_ripple_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_material_material_ripple_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Material Ripple
 Short Name: material-ripple-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/material/material-ripple-android/1.11.0-SNAPSHOT/material-ripple-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/material/material-ripple-android/1.11.0-SNAPSHOT/material-ripple-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_android/README.chromium
index 3dddd7d..5cbc0d7 100644
--- a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Runtime
 Short Name: runtime-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/runtime/runtime-android/1.11.0-SNAPSHOT/runtime-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/runtime/runtime-android/1.11.0-SNAPSHOT/runtime-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_annotation_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_annotation_android/README.chromium
index 7da19ea6..1647a7b 100644
--- a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_annotation_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_annotation_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Runtime Annotation
 Short Name: runtime-annotation-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/runtime/runtime-annotation-android/1.11.0-SNAPSHOT/runtime-annotation-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/runtime/runtime-annotation-android/1.11.0-SNAPSHOT/runtime-annotation-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_retain_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_retain_android/README.chromium
index db46cf4..6232884 100644
--- a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_retain_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_retain_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Runtime Retain
 Short Name: runtime-retain-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/runtime/runtime-retain-android/1.11.0-SNAPSHOT/runtime-retain-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/runtime/runtime-retain-android/1.11.0-SNAPSHOT/runtime-retain-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_saveable_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_saveable_android/README.chromium
index 5eefe48..ec65a46 100644
--- a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_saveable_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_saveable_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Saveable
 Short Name: runtime-saveable-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/runtime/runtime-saveable-android/1.11.0-SNAPSHOT/runtime-saveable-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/runtime/runtime-saveable-android/1.11.0-SNAPSHOT/runtime-saveable-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_android/README.chromium
index f858b5b..82474480 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose UI
 Short Name: ui-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/ui/ui-android/1.11.0-SNAPSHOT/ui-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/ui/ui-android/1.11.0-SNAPSHOT/ui-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_geometry_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_geometry_android/README.chromium
index 8200135..46a3e53 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_geometry_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_geometry_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Geometry
 Short Name: ui-geometry-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/ui/ui-geometry-android/1.11.0-SNAPSHOT/ui-geometry-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/ui/ui-geometry-android/1.11.0-SNAPSHOT/ui-geometry-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_graphics_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_graphics_android/README.chromium
index 21fabce..e3b64a2 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_graphics_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_graphics_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Graphics
 Short Name: ui-graphics-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/ui/ui-graphics-android/1.11.0-SNAPSHOT/ui-graphics-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/ui/ui-graphics-android/1.11.0-SNAPSHOT/ui-graphics-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_android/README.chromium
index dbce352..b595446 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Testing
 Short Name: ui-test-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/ui/ui-test-android/1.11.0-SNAPSHOT/ui-test-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/ui/ui-test-android/1.11.0-SNAPSHOT/ui-test-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_junit4_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_junit4_android/README.chromium
index 06a33a4eb..1e3c0121 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_junit4_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_junit4_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Testing for JUnit4
 Short Name: ui-test-junit4-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/ui/ui-test-junit4-android/1.11.0-SNAPSHOT/ui-test-junit4-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/ui/ui-test-junit4-android/1.11.0-SNAPSHOT/ui-test-junit4-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_manifest/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_manifest/README.chromium
index e1694840..937905b 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_manifest/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_manifest/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Testing manifest dependency
 Short Name: ui-test-manifest
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/ui/ui-test-manifest/1.11.0-SNAPSHOT/ui-test-manifest-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/ui/ui-test-manifest/1.11.0-SNAPSHOT/ui-test-manifest-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_android/README.chromium
index 142cce6b..952c26f 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose UI Text
 Short Name: ui-text-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/ui/ui-text-android/1.11.0-SNAPSHOT/ui-text-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/ui/ui-text-android/1.11.0-SNAPSHOT/ui-text-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_google_fonts/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_google_fonts/README.chromium
index 9c81b70..9aebe6d9c 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_google_fonts/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_google_fonts/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Google Fonts integration
 Short Name: ui-text-google-fonts
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/ui/ui-text-google-fonts/1.11.0-SNAPSHOT/ui-text-google-fonts-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/ui/ui-text-google-fonts/1.11.0-SNAPSHOT/ui-text-google-fonts-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_unit_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_unit_android/README.chromium
index 86296a2..5a063254 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_unit_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_unit_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Unit
 Short Name: ui-unit-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/ui/ui-unit-android/1.11.0-SNAPSHOT/ui-unit-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/ui/ui-unit-android/1.11.0-SNAPSHOT/ui-unit-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_util_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_util_android/README.chromium
index 5cfe1985..19e7813 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_util_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_util_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Util
 Short Name: ui-util-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/compose/ui/ui-util-android/1.11.0-SNAPSHOT/ui-util-android-1.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/compose/ui/ui-util-android/1.11.0-SNAPSHOT/ui-util-android-1.11.0-20260225.210851-1.aar
 Version: 1.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout/README.chromium b/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout/README.chromium
index c48a0e46..d67510d9 100644
--- a/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout/README.chromium
@@ -1,6 +1,6 @@
 Name: ConstraintLayout
 Short Name: constraintlayout
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/constraintlayout/constraintlayout/2.3.0-SNAPSHOT/constraintlayout-2.3.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/constraintlayout/constraintlayout/2.3.0-SNAPSHOT/constraintlayout-2.3.0-20260225.210851-1.aar
 Version: 2.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout_core/README.chromium b/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout_core/README.chromium
index e2ce64f6..5f6f6d2 100644
--- a/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout_core/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout_core/README.chromium
@@ -1,6 +1,6 @@
 Name: ConstraintLayout Core
 Short Name: constraintlayout-core
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/constraintlayout/constraintlayout-core/1.2.0-SNAPSHOT/constraintlayout-core-1.2.0-20260225.133501-1.jar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/constraintlayout/constraintlayout-core/1.2.0-SNAPSHOT/constraintlayout-core-1.2.0-20260225.210851-1.jar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_core_core/README.chromium b/third_party/androidx/committed/libs/androidx_core_core/README.chromium
index 46cafa41..b6c2153 100644
--- a/third_party/androidx/committed/libs/androidx_core_core/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_core_core/README.chromium
@@ -1,6 +1,6 @@
 Name: Core
 Short Name: core
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/core/core/1.18.0-SNAPSHOT/core-1.18.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/core/core/1.18.0-SNAPSHOT/core-1.18.0-20260225.210851-1.aar
 Version: 1.18.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_core_core_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_core_core_ktx/README.chromium
index 9b29472..a1f78c0 100644
--- a/third_party/androidx/committed/libs/androidx_core_core_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_core_core_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: Core Kotlin Extensions
 Short Name: core-ktx
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/core/core-ktx/1.18.0-SNAPSHOT/core-ktx-1.18.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/core/core-ktx/1.18.0-SNAPSHOT/core-ktx-1.18.0-20260225.210851-1.aar
 Version: 1.18.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_core_core_viewtree/README.chromium b/third_party/androidx/committed/libs/androidx_core_core_viewtree/README.chromium
index d423ed0..c128b0e 100644
--- a/third_party/androidx/committed/libs/androidx_core_core_viewtree/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_core_core_viewtree/README.chromium
@@ -1,6 +1,6 @@
 Name: androidx.core:core-viewtree
 Short Name: core-viewtree
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/core/core-viewtree/1.1.0-SNAPSHOT/core-viewtree-1.1.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/core/core-viewtree/1.1.0-SNAPSHOT/core-viewtree-1.1.0-20260225.210851-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_credentials_credentials/README.chromium b/third_party/androidx/committed/libs/androidx_credentials_credentials/README.chromium
index 3683ab8..e07f0049 100644
--- a/third_party/androidx/committed/libs/androidx_credentials_credentials/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_credentials_credentials/README.chromium
@@ -1,6 +1,6 @@
 Name: Credentials
 Short Name: credentials
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/credentials/credentials/1.6.0-SNAPSHOT/credentials-1.6.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/credentials/credentials/1.6.0-SNAPSHOT/credentials-1.6.0-20260225.210851-1.aar
 Version: 1.6.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_credentials_credentials_play_services_auth/README.chromium b/third_party/androidx/committed/libs/androidx_credentials_credentials_play_services_auth/README.chromium
index 649c003..b88325d2 100644
--- a/third_party/androidx/committed/libs/androidx_credentials_credentials_play_services_auth/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_credentials_credentials_play_services_auth/README.chromium
@@ -1,6 +1,6 @@
 Name: Credentials Play Services Auth
 Short Name: credentials-play-services-auth
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/credentials/credentials-play-services-auth/1.6.0-SNAPSHOT/credentials-play-services-auth-1.6.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/credentials/credentials-play-services-auth/1.6.0-SNAPSHOT/credentials-play-services-auth-1.6.0-20260225.210851-1.aar
 Version: 1.6.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider/README.chromium b/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider/README.chromium
index eb4c1ee..61d82b4 100644
--- a/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider/README.chromium
@@ -1,6 +1,6 @@
 Name: androidx.credentials.registry:registry-provider
 Short Name: registry-provider
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/credentials/registry/registry-provider/1.0.0-SNAPSHOT/registry-provider-1.0.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/credentials/registry/registry-provider/1.0.0-SNAPSHOT/registry-provider-1.0.0-20260225.210851-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider_play_services/README.chromium b/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider_play_services/README.chromium
index b2477ee..cf31398c 100644
--- a/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider_play_services/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider_play_services/README.chromium
@@ -1,6 +1,6 @@
 Name: androidx.credentials.registry:registry-provider-play-services
 Short Name: registry-provider-play-services
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/credentials/registry/registry-provider-play-services/1.0.0-SNAPSHOT/registry-provider-play-services-1.0.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/credentials/registry/registry-provider-play-services/1.0.0-SNAPSHOT/registry-provider-play-services-1.0.0-20260225.210851-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_cursoradapter_cursoradapter/README.chromium b/third_party/androidx/committed/libs/androidx_cursoradapter_cursoradapter/README.chromium
index a2cf5ab..42dc3fb 100644
--- a/third_party/androidx/committed/libs/androidx_cursoradapter_cursoradapter/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_cursoradapter_cursoradapter/README.chromium
@@ -1,6 +1,6 @@
 Name: Cursor Adapter
 Short Name: cursoradapter
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/cursoradapter/cursoradapter/1.1.0-SNAPSHOT/cursoradapter-1.1.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/cursoradapter/cursoradapter/1.1.0-SNAPSHOT/cursoradapter-1.1.0-20260225.210851-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_android/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_android/README.chromium
index ee260c46..ceb49f73 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_android/README.chromium
@@ -1,6 +1,6 @@
 Name: DataStore
 Short Name: datastore-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/datastore/datastore-android/1.3.0-SNAPSHOT/datastore-android-1.3.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/datastore/datastore-android/1.3.0-SNAPSHOT/datastore-android-1.3.0-20260225.210851-1.aar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_core_android/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_core_android/README.chromium
index c46d552..3df895c 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_core_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_core_android/README.chromium
@@ -1,6 +1,6 @@
 Name: DataStore Core
 Short Name: datastore-core-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/datastore/datastore-core-android/1.3.0-SNAPSHOT/datastore-core-android-1.3.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/datastore/datastore-core-android/1.3.0-SNAPSHOT/datastore-core-android-1.3.0-20260225.210851-1.aar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_core_okio_jvm/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_core_okio_jvm/README.chromium
index 95784c9..29cf564 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_core_okio_jvm/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_core_okio_jvm/README.chromium
@@ -1,6 +1,6 @@
 Name: DataStore Core Okio
 Short Name: datastore-core-okio-jvm
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/datastore/datastore-core-okio-jvm/1.3.0-SNAPSHOT/datastore-core-okio-jvm-1.3.0-20260225.133501-1.jar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/datastore/datastore-core-okio-jvm/1.3.0-SNAPSHOT/datastore-core-okio-jvm-1.3.0-20260225.210851-1.jar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_android/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_android/README.chromium
index ff930ca..b1255546 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Preferences DataStore
 Short Name: datastore-preferences-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/datastore/datastore-preferences-android/1.3.0-SNAPSHOT/datastore-preferences-android-1.3.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/datastore/datastore-preferences-android/1.3.0-SNAPSHOT/datastore-preferences-android-1.3.0-20260225.210851-1.aar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_core_android/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_core_android/README.chromium
index ca906e8..3b9c116 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_core_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_core_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Preferences DataStore Core
 Short Name: datastore-preferences-core-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/datastore/datastore-preferences-core-android/1.3.0-SNAPSHOT/datastore-preferences-core-android-1.3.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/datastore/datastore-preferences-core-android/1.3.0-SNAPSHOT/datastore-preferences-core-android-1.3.0-20260225.210851-1.aar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_external_protobuf/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_external_protobuf/README.chromium
index a23de7f..8d0f50c 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_external_protobuf/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_external_protobuf/README.chromium
@@ -1,6 +1,6 @@
 Name: Preferences External Protobuf
 Short Name: datastore-preferences-external-protobuf
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/datastore/datastore-preferences-external-protobuf/1.3.0-SNAPSHOT/datastore-preferences-external-protobuf-1.3.0-20260225.133501-1.jar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/datastore/datastore-preferences-external-protobuf/1.3.0-SNAPSHOT/datastore-preferences-external-protobuf-1.3.0-20260225.210851-1.jar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: BSD-3-Clause
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_proto/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_proto/README.chromium
index fc605bb..c21ff28 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_proto/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_proto/README.chromium
@@ -1,6 +1,6 @@
 Name: Preferences DataStore Proto
 Short Name: datastore-preferences-proto
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/datastore/datastore-preferences-proto/1.3.0-SNAPSHOT/datastore-preferences-proto-1.3.0-20260225.133501-1.jar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/datastore/datastore-preferences-proto/1.3.0-SNAPSHOT/datastore-preferences-proto-1.3.0-20260225.210851-1.jar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_drawerlayout_drawerlayout/README.chromium b/third_party/androidx/committed/libs/androidx_drawerlayout_drawerlayout/README.chromium
index 6fe9fe06..87fc62e 100644
--- a/third_party/androidx/committed/libs/androidx_drawerlayout_drawerlayout/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_drawerlayout_drawerlayout/README.chromium
@@ -1,6 +1,6 @@
 Name: Drawer Layout
 Short Name: drawerlayout
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/drawerlayout/drawerlayout/1.3.0-SNAPSHOT/drawerlayout-1.3.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/drawerlayout/drawerlayout/1.3.0-SNAPSHOT/drawerlayout-1.3.0-20260225.210851-1.aar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_fragment_fragment/README.chromium b/third_party/androidx/committed/libs/androidx_fragment_fragment/README.chromium
index 21c723b..f827697 100644
--- a/third_party/androidx/committed/libs/androidx_fragment_fragment/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_fragment_fragment/README.chromium
@@ -1,6 +1,6 @@
 Name: fragment
 Short Name: fragment
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/fragment/fragment/1.9.0-SNAPSHOT/fragment-1.9.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/fragment/fragment/1.9.0-SNAPSHOT/fragment-1.9.0-20260225.210851-1.aar
 Version: 1.9.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_fragment_fragment_compose/README.chromium b/third_party/androidx/committed/libs/androidx_fragment_fragment_compose/README.chromium
index bf4514f..349eee96 100644
--- a/third_party/androidx/committed/libs/androidx_fragment_fragment_compose/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_fragment_fragment_compose/README.chromium
@@ -1,6 +1,6 @@
 Name: Fragment Compose
 Short Name: fragment-compose
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/fragment/fragment-compose/1.9.0-SNAPSHOT/fragment-compose-1.9.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/fragment/fragment-compose/1.9.0-SNAPSHOT/fragment-compose-1.9.0-20260225.210851-1.aar
 Version: 1.9.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_fragment_fragment_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_fragment_fragment_ktx/README.chromium
index 1d1c40b..f3eaca5 100644
--- a/third_party/androidx/committed/libs/androidx_fragment_fragment_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_fragment_fragment_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: Fragment Kotlin Extensions
 Short Name: fragment-ktx
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/fragment/fragment-ktx/1.9.0-SNAPSHOT/fragment-ktx-1.9.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/fragment/fragment-ktx/1.9.0-SNAPSHOT/fragment-ktx-1.9.0-20260225.210851-1.aar
 Version: 1.9.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_fragment_fragment_testing/README.chromium b/third_party/androidx/committed/libs/androidx_fragment_fragment_testing/README.chromium
index b229e21..7385d27 100644
--- a/third_party/androidx/committed/libs/androidx_fragment_fragment_testing/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_fragment_fragment_testing/README.chromium
@@ -1,6 +1,6 @@
 Name: Fragment Testing Extensions
 Short Name: fragment-testing
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/fragment/fragment-testing/1.9.0-SNAPSHOT/fragment-testing-1.9.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/fragment/fragment-testing/1.9.0-SNAPSHOT/fragment-testing-1.9.0-20260225.210851-1.aar
 Version: 1.9.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_fragment_fragment_testing_manifest/README.chromium b/third_party/androidx/committed/libs/androidx_fragment_fragment_testing_manifest/README.chromium
index 7aaa096..bf76d728 100644
--- a/third_party/androidx/committed/libs/androidx_fragment_fragment_testing_manifest/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_fragment_fragment_testing_manifest/README.chromium
@@ -1,6 +1,6 @@
 Name: Fragment Testing Manifest dependency
 Short Name: fragment-testing-manifest
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/fragment/fragment-testing-manifest/1.9.0-SNAPSHOT/fragment-testing-manifest-1.9.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/fragment/fragment-testing-manifest/1.9.0-SNAPSHOT/fragment-testing-manifest-1.9.0-20260225.210851-1.aar
 Version: 1.9.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_graphics_graphics_path/README.chromium b/third_party/androidx/committed/libs/androidx_graphics_graphics_path/README.chromium
index af79f7e..ec5cb98 100644
--- a/third_party/androidx/committed/libs/androidx_graphics_graphics_path/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_graphics_graphics_path/README.chromium
@@ -1,6 +1,6 @@
 Name: Android Graphics Path
 Short Name: graphics-path
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/graphics/graphics-path/1.1.0-SNAPSHOT/graphics-path-1.1.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/graphics/graphics-path/1.1.0-SNAPSHOT/graphics-path-1.1.0-20260225.210851-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_interpolator_interpolator/README.chromium b/third_party/androidx/committed/libs/androidx_interpolator_interpolator/README.chromium
index ffe33b17..b610467a 100644
--- a/third_party/androidx/committed/libs/androidx_interpolator_interpolator/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_interpolator_interpolator/README.chromium
@@ -1,6 +1,6 @@
 Name: Interpolators
 Short Name: interpolator
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/interpolator/interpolator/1.1.0-SNAPSHOT/interpolator-1.1.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/interpolator/interpolator/1.1.0-SNAPSHOT/interpolator-1.1.0-20260225.210851-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_leanback_leanback/README.chromium b/third_party/androidx/committed/libs/androidx_leanback_leanback/README.chromium
index 3afabff..6e1ce0d 100644
--- a/third_party/androidx/committed/libs/androidx_leanback_leanback/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_leanback_leanback/README.chromium
@@ -1,6 +1,6 @@
 Name: Leanback
 Short Name: leanback
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/leanback/leanback/1.3.0-SNAPSHOT/leanback-1.3.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/leanback/leanback/1.3.0-SNAPSHOT/leanback-1.3.0-20260225.210851-1.aar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_leanback_leanback_grid/README.chromium b/third_party/androidx/committed/libs/androidx_leanback_leanback_grid/README.chromium
index 5b3fd9f..faa1404 100644
--- a/third_party/androidx/committed/libs/androidx_leanback_leanback_grid/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_leanback_leanback_grid/README.chromium
@@ -1,6 +1,6 @@
 Name: Leanback Grid
 Short Name: leanback-grid
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/leanback/leanback-grid/1.1.0-SNAPSHOT/leanback-grid-1.1.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/leanback/leanback-grid/1.1.0-SNAPSHOT/leanback-grid-1.1.0-20260225.210851-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_java8/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_java8/README.chromium
index b991615..8ef7674 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_java8/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_java8/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle-Common for Java 8
 Short Name: lifecycle-common-java8
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-common-java8/2.11.0-SNAPSHOT/lifecycle-common-java8-2.11.0-20260225.133501-1.jar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-common-java8/2.11.0-SNAPSHOT/lifecycle-common-java8-2.11.0-20260225.210851-1.jar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_jvm/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_jvm/README.chromium
index df6e7c6..b6d16db 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_jvm/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_jvm/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle-Common
 Short Name: lifecycle-common-jvm
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-common-jvm/2.11.0-SNAPSHOT/lifecycle-common-jvm-2.11.0-20260225.133501-1.jar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-common-jvm/2.11.0-SNAPSHOT/lifecycle-common-jvm-2.11.0-20260225.210851-1.jar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata/README.chromium
index 4410b64..c8e775c 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle LiveData
 Short Name: lifecycle-livedata
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-livedata/2.11.0-SNAPSHOT/lifecycle-livedata-2.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-livedata/2.11.0-SNAPSHOT/lifecycle-livedata-2.11.0-20260225.210851-1.aar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core/README.chromium
index d2d64b3..48f0db7 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle LiveData Core
 Short Name: lifecycle-livedata-core
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-livedata-core/2.11.0-SNAPSHOT/lifecycle-livedata-core-2.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-livedata-core/2.11.0-SNAPSHOT/lifecycle-livedata-core-2.11.0-20260225.210851-1.aar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core_ktx/README.chromium
index ec3a07f..8198ae9 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: LiveData Core Kotlin Extensions
 Short Name: lifecycle-livedata-core-ktx
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-livedata-core-ktx/2.11.0-SNAPSHOT/lifecycle-livedata-core-ktx-2.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-livedata-core-ktx/2.11.0-SNAPSHOT/lifecycle-livedata-core-ktx-2.11.0-20260225.210851-1.aar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_ktx/README.chromium
index 46be235..ae71175d 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: LiveData Kotlin Extensions
 Short Name: lifecycle-livedata-ktx
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-livedata-ktx/2.11.0-SNAPSHOT/lifecycle-livedata-ktx-2.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-livedata-ktx/2.11.0-SNAPSHOT/lifecycle-livedata-ktx-2.11.0-20260225.210851-1.aar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_process/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_process/README.chromium
index 0acad23..b4cec60 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_process/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_process/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle Process
 Short Name: lifecycle-process
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-process/2.11.0-SNAPSHOT/lifecycle-process-2.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-process/2.11.0-SNAPSHOT/lifecycle-process-2.11.0-20260225.210851-1.aar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_android/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_android/README.chromium
index 4860fcf..dadceff 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle Runtime
 Short Name: lifecycle-runtime-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-runtime-android/2.11.0-SNAPSHOT/lifecycle-runtime-android-2.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-runtime-android/2.11.0-SNAPSHOT/lifecycle-runtime-android-2.11.0-20260225.210851-1.aar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_compose_android/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_compose_android/README.chromium
index cc205f8..dd774c3 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_compose_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_compose_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle Runtime Compose
 Short Name: lifecycle-runtime-compose-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-runtime-compose-android/2.11.0-SNAPSHOT/lifecycle-runtime-compose-android-2.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-runtime-compose-android/2.11.0-SNAPSHOT/lifecycle-runtime-compose-android-2.11.0-20260225.210851-1.aar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_ktx_android/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_ktx_android/README.chromium
index 97aba8c6..7ddabf51 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_ktx_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_ktx_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle Kotlin Extensions
 Short Name: lifecycle-runtime-ktx-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-runtime-ktx-android/2.11.0-SNAPSHOT/lifecycle-runtime-ktx-android-2.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-runtime-ktx-android/2.11.0-SNAPSHOT/lifecycle-runtime-ktx-android-2.11.0-20260225.210851-1.aar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_service/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_service/README.chromium
index a78d35a3..b2cd1a0e 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_service/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_service/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle Service
 Short Name: lifecycle-service
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-service/2.11.0-SNAPSHOT/lifecycle-service-2.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-service/2.11.0-SNAPSHOT/lifecycle-service-2.11.0-20260225.210851-1.aar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_android/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_android/README.chromium
index 4b36d782..e78fb52 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle ViewModel
 Short Name: lifecycle-viewmodel-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-android/2.11.0-SNAPSHOT/lifecycle-viewmodel-android-2.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-android/2.11.0-SNAPSHOT/lifecycle-viewmodel-android-2.11.0-20260225.210851-1.aar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_compose_android/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_compose_android/README.chromium
index 7c364b4a..d7c675e7 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_compose_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_compose_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle ViewModel Compose
 Short Name: lifecycle-viewmodel-compose-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-compose-android/2.11.0-SNAPSHOT/lifecycle-viewmodel-compose-android-2.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-compose-android/2.11.0-SNAPSHOT/lifecycle-viewmodel-compose-android-2.11.0-20260225.210851-1.aar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_ktx/README.chromium
index ca5bc1f8..1d59e9f 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle ViewModel Kotlin Extensions
 Short Name: lifecycle-viewmodel-ktx
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-ktx/2.11.0-SNAPSHOT/lifecycle-viewmodel-ktx-2.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-ktx/2.11.0-SNAPSHOT/lifecycle-viewmodel-ktx-2.11.0-20260225.210851-1.aar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_savedstate_android/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_savedstate_android/README.chromium
index 5d865510..4981115 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_savedstate_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_savedstate_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle ViewModel with SavedState
 Short Name: lifecycle-viewmodel-savedstate-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-savedstate-android/2.11.0-SNAPSHOT/lifecycle-viewmodel-savedstate-android-2.11.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-savedstate-android/2.11.0-SNAPSHOT/lifecycle-viewmodel-savedstate-android-2.11.0-20260225.210851-1.aar
 Version: 2.11.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_loader_loader/README.chromium b/third_party/androidx/committed/libs/androidx_loader_loader/README.chromium
index e2e90a5..62375bc 100644
--- a/third_party/androidx/committed/libs/androidx_loader_loader/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_loader_loader/README.chromium
@@ -1,6 +1,6 @@
 Name: loader
 Short Name: loader
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/loader/loader/1.2.0-SNAPSHOT/loader-1.2.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/loader/loader/1.2.0-SNAPSHOT/loader-1.2.0-20260225.210851-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_media_media/README.chromium b/third_party/androidx/committed/libs/androidx_media_media/README.chromium
index d17e711..7bfd9fe 100644
--- a/third_party/androidx/committed/libs/androidx_media_media/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_media_media/README.chromium
@@ -1,6 +1,6 @@
 Name: Media
 Short Name: media
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/media/media/1.8.0-SNAPSHOT/media-1.8.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/media/media/1.8.0-SNAPSHOT/media-1.8.0-20260225.210851-1.aar
 Version: 1.8.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_mediarouter_mediarouter/README.chromium b/third_party/androidx/committed/libs/androidx_mediarouter_mediarouter/README.chromium
index b6be9f3..2f74022 100644
--- a/third_party/androidx/committed/libs/androidx_mediarouter_mediarouter/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_mediarouter_mediarouter/README.chromium
@@ -1,6 +1,6 @@
 Name: MediaRouter
 Short Name: mediarouter
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/mediarouter/mediarouter/1.9.0-SNAPSHOT/mediarouter-1.9.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/mediarouter/mediarouter/1.9.0-SNAPSHOT/mediarouter-1.9.0-20260225.210851-1.aar
 Version: 1.9.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_navigation_navigation_common_android/README.chromium b/third_party/androidx/committed/libs/androidx_navigation_navigation_common_android/README.chromium
index 9931057..7d8a7df 100644
--- a/third_party/androidx/committed/libs/androidx_navigation_navigation_common_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_navigation_navigation_common_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Navigation Common
 Short Name: navigation-common-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/navigation/navigation-common-android/2.10.0-SNAPSHOT/navigation-common-android-2.10.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/navigation/navigation-common-android/2.10.0-SNAPSHOT/navigation-common-android-2.10.0-20260225.210851-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_navigation_navigation_compose_android/README.chromium b/third_party/androidx/committed/libs/androidx_navigation_navigation_compose_android/README.chromium
index 03f9002f..83ceea8 100644
--- a/third_party/androidx/committed/libs/androidx_navigation_navigation_compose_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_navigation_navigation_compose_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Navigation
 Short Name: navigation-compose-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/navigation/navigation-compose-android/2.10.0-SNAPSHOT/navigation-compose-android-2.10.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/navigation/navigation-compose-android/2.10.0-SNAPSHOT/navigation-compose-android-2.10.0-20260225.210851-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_navigation_navigation_runtime_android/README.chromium b/third_party/androidx/committed/libs/androidx_navigation_navigation_runtime_android/README.chromium
index 32a7dec..d122aadf 100644
--- a/third_party/androidx/committed/libs/androidx_navigation_navigation_runtime_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_navigation_navigation_runtime_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Navigation Runtime
 Short Name: navigation-runtime-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/navigation/navigation-runtime-android/2.10.0-SNAPSHOT/navigation-runtime-android-2.10.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/navigation/navigation-runtime-android/2.10.0-SNAPSHOT/navigation-runtime-android-2.10.0-20260225.210851-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_android/README.chromium b/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_android/README.chromium
index 6f0e914..cd2f2c5 100644
--- a/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Navigation Event
 Short Name: navigationevent-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/navigationevent/navigationevent-android/1.1.0-SNAPSHOT/navigationevent-android-1.1.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/navigationevent/navigationevent-android/1.1.0-SNAPSHOT/navigationevent-android-1.1.0-20260225.210851-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_compose_android/README.chromium b/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_compose_android/README.chromium
index 3f149cf..108b7e5 100644
--- a/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_compose_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_compose_android/README.chromium
@@ -1,6 +1,6 @@
 Name: NavigationEvent Compose
 Short Name: navigationevent-compose-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/navigationevent/navigationevent-compose-android/1.1.0-SNAPSHOT/navigationevent-compose-android-1.1.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/navigationevent/navigationevent-compose-android/1.1.0-SNAPSHOT/navigationevent-compose-android-1.1.0-20260225.210851-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_paging_paging_common_android/README.chromium b/third_party/androidx/committed/libs/androidx_paging_paging_common_android/README.chromium
index ded844c..b8de24a3 100644
--- a/third_party/androidx/committed/libs/androidx_paging_paging_common_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_paging_paging_common_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Paging-Common
 Short Name: paging-common-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/paging/paging-common-android/3.5.0-SNAPSHOT/paging-common-android-3.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/paging/paging-common-android/3.5.0-SNAPSHOT/paging-common-android-3.5.0-20260225.210851-1.aar
 Version: 3.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_paging_paging_common_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_paging_paging_common_ktx/README.chromium
index 52d6285..7bb2f16e 100644
--- a/third_party/androidx/committed/libs/androidx_paging_paging_common_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_paging_paging_common_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: Paging-Common Kotlin Extensions
 Short Name: paging-common-ktx
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/paging/paging-common-ktx/3.5.0-SNAPSHOT/paging-common-ktx-3.5.0-20260225.133501-1.jar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/paging/paging-common-ktx/3.5.0-SNAPSHOT/paging-common-ktx-3.5.0-20260225.210851-1.jar
 Version: 3.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_paging_paging_compose_android/README.chromium b/third_party/androidx/committed/libs/androidx_paging_paging_compose_android/README.chromium
index 8cd24636..214a48c8 100644
--- a/third_party/androidx/committed/libs/androidx_paging_paging_compose_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_paging_paging_compose_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Paging-Compose
 Short Name: paging-compose-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/paging/paging-compose-android/3.5.0-SNAPSHOT/paging-compose-android-3.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/paging/paging-compose-android/3.5.0-SNAPSHOT/paging-compose-android-3.5.0-20260225.210851-1.aar
 Version: 3.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_paging_paging_runtime/README.chromium b/third_party/androidx/committed/libs/androidx_paging_paging_runtime/README.chromium
index 2f6a702..be3c33a 100644
--- a/third_party/androidx/committed/libs/androidx_paging_paging_runtime/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_paging_paging_runtime/README.chromium
@@ -1,6 +1,6 @@
 Name: Paging-Runtime
 Short Name: paging-runtime
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/paging/paging-runtime/3.5.0-SNAPSHOT/paging-runtime-3.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/paging/paging-runtime/3.5.0-SNAPSHOT/paging-runtime-3.5.0-20260225.210851-1.aar
 Version: 3.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_palette_palette/README.chromium b/third_party/androidx/committed/libs/androidx_palette_palette/README.chromium
index 8f07105..89bb076f 100644
--- a/third_party/androidx/committed/libs/androidx_palette_palette/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_palette_palette/README.chromium
@@ -1,6 +1,6 @@
 Name: Palette
 Short Name: palette
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/palette/palette/1.1.0-SNAPSHOT/palette-1.1.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/palette/palette/1.1.0-SNAPSHOT/palette-1.1.0-20260225.210851-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_pdf_pdf_document_service/README.chromium b/third_party/androidx/committed/libs/androidx_pdf_pdf_document_service/README.chromium
index a57d7f1..72b82bc5d 100644
--- a/third_party/androidx/committed/libs/androidx_pdf_pdf_document_service/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_pdf_pdf_document_service/README.chromium
@@ -1,6 +1,6 @@
 Name: androidx.pdf:pdf-document-service
 Short Name: pdf-document-service
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/pdf/pdf-document-service/1.0.0-SNAPSHOT/pdf-document-service-1.0.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/pdf/pdf-document-service/1.0.0-SNAPSHOT/pdf-document-service-1.0.0-20260225.210851-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer/README.chromium b/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer/README.chromium
index e68d6e6..5291e32 100644
--- a/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer/README.chromium
@@ -1,6 +1,6 @@
 Name: androidx.pdf:pdf-viewer
 Short Name: pdf-viewer
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/pdf/pdf-viewer/1.0.0-SNAPSHOT/pdf-viewer-1.0.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/pdf/pdf-viewer/1.0.0-SNAPSHOT/pdf-viewer-1.0.0-20260225.210851-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer_fragment/README.chromium b/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer_fragment/README.chromium
index 0718fcc..3e3ed02 100644
--- a/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer_fragment/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer_fragment/README.chromium
@@ -1,6 +1,6 @@
 Name: androidx.pdf:pdf-viewer-fragment
 Short Name: pdf-viewer-fragment
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/pdf/pdf-viewer-fragment/1.0.0-SNAPSHOT/pdf-viewer-fragment-1.0.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/pdf/pdf-viewer-fragment/1.0.0-SNAPSHOT/pdf-viewer-fragment-1.0.0-20260225.210851-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_preference_preference/README.chromium b/third_party/androidx/committed/libs/androidx_preference_preference/README.chromium
index e96c36d..0370667 100644
--- a/third_party/androidx/committed/libs/androidx_preference_preference/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_preference_preference/README.chromium
@@ -1,6 +1,6 @@
 Name: Preference
 Short Name: preference
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/preference/preference/1.3.0-SNAPSHOT/preference-1.3.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/preference/preference/1.3.0-SNAPSHOT/preference-1.3.0-20260225.210851-1.aar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_profileinstaller_profileinstaller/README.chromium b/third_party/androidx/committed/libs/androidx_profileinstaller_profileinstaller/README.chromium
index f41d404..2bd872a 100644
--- a/third_party/androidx/committed/libs/androidx_profileinstaller_profileinstaller/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_profileinstaller_profileinstaller/README.chromium
@@ -1,6 +1,6 @@
 Name: Profile Installer
 Short Name: profileinstaller
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/profileinstaller/profileinstaller/1.5.0-SNAPSHOT/profileinstaller-1.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/profileinstaller/profileinstaller/1.5.0-SNAPSHOT/profileinstaller-1.5.0-20260225.210851-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_recyclerview_recyclerview/README.chromium b/third_party/androidx/committed/libs/androidx_recyclerview_recyclerview/README.chromium
index 71449087..3c35f5e 100644
--- a/third_party/androidx/committed/libs/androidx_recyclerview_recyclerview/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_recyclerview_recyclerview/README.chromium
@@ -1,6 +1,6 @@
 Name: RecyclerView
 Short Name: recyclerview
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/recyclerview/recyclerview/1.5.0-SNAPSHOT/recyclerview-1.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/recyclerview/recyclerview/1.5.0-SNAPSHOT/recyclerview-1.5.0-20260225.210851-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_resourceinspection_resourceinspection_annotation/README.chromium b/third_party/androidx/committed/libs/androidx_resourceinspection_resourceinspection_annotation/README.chromium
index e8879da..65ac229 100644
--- a/third_party/androidx/committed/libs/androidx_resourceinspection_resourceinspection_annotation/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_resourceinspection_resourceinspection_annotation/README.chromium
@@ -1,6 +1,6 @@
 Name: Resource Inspection - Annotations
 Short Name: resourceinspection-annotation
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/resourceinspection/resourceinspection-annotation/1.1.0-SNAPSHOT/resourceinspection-annotation-1.1.0-20260225.133501-1.jar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/resourceinspection/resourceinspection-annotation/1.1.0-SNAPSHOT/resourceinspection-annotation-1.1.0-20260225.210851-1.jar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_savedstate_savedstate_android/README.chromium b/third_party/androidx/committed/libs/androidx_savedstate_savedstate_android/README.chromium
index 74be129f..4e50a9d0 100644
--- a/third_party/androidx/committed/libs/androidx_savedstate_savedstate_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_savedstate_savedstate_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Saved State
 Short Name: savedstate-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/savedstate/savedstate-android/1.5.0-SNAPSHOT/savedstate-android-1.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/savedstate/savedstate-android/1.5.0-SNAPSHOT/savedstate-android-1.5.0-20260225.210851-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_savedstate_savedstate_compose_android/README.chromium b/third_party/androidx/committed/libs/androidx_savedstate_savedstate_compose_android/README.chromium
index 202609e..6349d51 100644
--- a/third_party/androidx/committed/libs/androidx_savedstate_savedstate_compose_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_savedstate_savedstate_compose_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Saved State Compose
 Short Name: savedstate-compose-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/savedstate/savedstate-compose-android/1.5.0-SNAPSHOT/savedstate-compose-android-1.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/savedstate/savedstate-compose-android/1.5.0-SNAPSHOT/savedstate-compose-android-1.5.0-20260225.210851-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_savedstate_savedstate_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_savedstate_savedstate_ktx/README.chromium
index 487b160..ed4c61f5 100644
--- a/third_party/androidx/committed/libs/androidx_savedstate_savedstate_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_savedstate_savedstate_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: SavedState Kotlin Extensions
 Short Name: savedstate-ktx
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/savedstate/savedstate-ktx/1.5.0-SNAPSHOT/savedstate-ktx-1.5.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/savedstate/savedstate-ktx/1.5.0-SNAPSHOT/savedstate-ktx-1.5.0-20260225.210851-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_slidingpanelayout_slidingpanelayout/README.chromium b/third_party/androidx/committed/libs/androidx_slidingpanelayout_slidingpanelayout/README.chromium
index a69a2e8..b9e88c96 100644
--- a/third_party/androidx/committed/libs/androidx_slidingpanelayout_slidingpanelayout/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_slidingpanelayout_slidingpanelayout/README.chromium
@@ -1,6 +1,6 @@
 Name: Sliding Pane Layout
 Short Name: slidingpanelayout
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/slidingpanelayout/slidingpanelayout/1.3.0-SNAPSHOT/slidingpanelayout-1.3.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/slidingpanelayout/slidingpanelayout/1.3.0-SNAPSHOT/slidingpanelayout-1.3.0-20260225.210851-1.aar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_sqlite_sqlite_android/README.chromium b/third_party/androidx/committed/libs/androidx_sqlite_sqlite_android/README.chromium
index f019d04..3826d4c 100644
--- a/third_party/androidx/committed/libs/androidx_sqlite_sqlite_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_sqlite_sqlite_android/README.chromium
@@ -1,6 +1,6 @@
 Name: SQLite
 Short Name: sqlite-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/sqlite/sqlite-android/2.7.0-SNAPSHOT/sqlite-android-2.7.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/sqlite/sqlite-android/2.7.0-SNAPSHOT/sqlite-android-2.7.0-20260225.210851-1.aar
 Version: 2.7.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_sqlite_sqlite_framework_android/README.chromium b/third_party/androidx/committed/libs/androidx_sqlite_sqlite_framework_android/README.chromium
index 9cf987fc..dc9bea5 100644
--- a/third_party/androidx/committed/libs/androidx_sqlite_sqlite_framework_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_sqlite_sqlite_framework_android/README.chromium
@@ -1,6 +1,6 @@
 Name: SQLite Framework Integration
 Short Name: sqlite-framework-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/sqlite/sqlite-framework-android/2.7.0-SNAPSHOT/sqlite-framework-android-2.7.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/sqlite/sqlite-framework-android/2.7.0-SNAPSHOT/sqlite-framework-android-2.7.0-20260225.210851-1.aar
 Version: 2.7.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_test_uiautomator_uiautomator/README.chromium b/third_party/androidx/committed/libs/androidx_test_uiautomator_uiautomator/README.chromium
index aa7d72e..e40bad5e6 100644
--- a/third_party/androidx/committed/libs/androidx_test_uiautomator_uiautomator/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_test_uiautomator_uiautomator/README.chromium
@@ -1,6 +1,6 @@
 Name: UIAutomator
 Short Name: uiautomator
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/test/uiautomator/uiautomator/2.4.0-SNAPSHOT/uiautomator-2.4.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/test/uiautomator/uiautomator/2.4.0-SNAPSHOT/uiautomator-2.4.0-20260225.210851-1.aar
 Version: 2.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_test_uiautomator_uiautomator_shell_android/README.chromium b/third_party/androidx/committed/libs/androidx_test_uiautomator_uiautomator_shell_android/README.chromium
index 626e4928..2d49555d 100644
--- a/third_party/androidx/committed/libs/androidx_test_uiautomator_uiautomator_shell_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_test_uiautomator_uiautomator_shell_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Shell
 Short Name: uiautomator-shell-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/test/uiautomator/uiautomator-shell-android/2.4.0-SNAPSHOT/uiautomator-shell-android-2.4.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/test/uiautomator/uiautomator-shell-android/2.4.0-SNAPSHOT/uiautomator-shell-android-2.4.0-20260225.210851-1.aar
 Version: 2.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_tracing_tracing_android/README.chromium b/third_party/androidx/committed/libs/androidx_tracing_tracing_android/README.chromium
index 485bc45..64ac513 100644
--- a/third_party/androidx/committed/libs/androidx_tracing_tracing_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_tracing_tracing_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Tracing
 Short Name: tracing-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/tracing/tracing-android/2.0.0-SNAPSHOT/tracing-android-2.0.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/tracing/tracing-android/2.0.0-SNAPSHOT/tracing-android-2.0.0-20260225.210851-1.aar
 Version: 2.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_tracing_tracing_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_tracing_tracing_ktx/README.chromium
index 78d5944..ffecda2 100644
--- a/third_party/androidx/committed/libs/androidx_tracing_tracing_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_tracing_tracing_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: Tracing Kotlin Extensions
 Short Name: tracing-ktx
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/tracing/tracing-ktx/2.0.0-SNAPSHOT/tracing-ktx-2.0.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/tracing/tracing-ktx/2.0.0-SNAPSHOT/tracing-ktx-2.0.0-20260225.210851-1.aar
 Version: 2.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_viewpager2_viewpager2/README.chromium b/third_party/androidx/committed/libs/androidx_viewpager2_viewpager2/README.chromium
index 5002cec..ba3fe54 100644
--- a/third_party/androidx/committed/libs/androidx_viewpager2_viewpager2/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_viewpager2_viewpager2/README.chromium
@@ -1,6 +1,6 @@
 Name: ViewPager2
 Short Name: viewpager2
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/viewpager2/viewpager2/1.2.0-SNAPSHOT/viewpager2-1.2.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/viewpager2/viewpager2/1.2.0-SNAPSHOT/viewpager2-1.2.0-20260225.210851-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_webkit_webkit/README.chromium b/third_party/androidx/committed/libs/androidx_webkit_webkit/README.chromium
index dddcfc9..724010d 100644
--- a/third_party/androidx/committed/libs/androidx_webkit_webkit/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_webkit_webkit/README.chromium
@@ -1,6 +1,6 @@
 Name: Webkit
 Short Name: webkit
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/webkit/webkit/1.16.0-SNAPSHOT/webkit-1.16.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/webkit/webkit/1.16.0-SNAPSHOT/webkit-1.16.0-20260225.210851-1.aar
 Version: 1.16.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_window_sidecar_sidecar/README.chromium b/third_party/androidx/committed/libs/androidx_window_sidecar_sidecar/README.chromium
index 25469aed..2cb77f0 100644
--- a/third_party/androidx/committed/libs/androidx_window_sidecar_sidecar/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_window_sidecar_sidecar/README.chromium
@@ -1,6 +1,6 @@
 Name: WindowManager Sidecar
 Short Name: sidecar
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/window/sidecar/sidecar/1.0.0-SNAPSHOT/sidecar-1.0.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/window/sidecar/sidecar/1.0.0-SNAPSHOT/sidecar-1.0.0-20260225.210851-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_window_window/README.chromium b/third_party/androidx/committed/libs/androidx_window_window/README.chromium
index 307fe7b..4626da66 100644
--- a/third_party/androidx/committed/libs/androidx_window_window/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_window_window/README.chromium
@@ -1,6 +1,6 @@
 Name: WindowManager
 Short Name: window
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/window/window/1.6.0-SNAPSHOT/window-1.6.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/window/window/1.6.0-SNAPSHOT/window-1.6.0-20260225.210851-1.aar
 Version: 1.6.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_window_window_core_android/README.chromium b/third_party/androidx/committed/libs/androidx_window_window_core_android/README.chromium
index 8083417a..e29667c0 100644
--- a/third_party/androidx/committed/libs/androidx_window_window_core_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_window_window_core_android/README.chromium
@@ -1,6 +1,6 @@
 Name: WindowManager Core
 Short Name: window-core-android
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/window/window-core-android/1.6.0-SNAPSHOT/window-core-android-1.6.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/window/window-core-android/1.6.0-SNAPSHOT/window-core-android-1.6.0-20260225.210851-1.aar
 Version: 1.6.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_work_work_multiprocess/README.chromium b/third_party/androidx/committed/libs/androidx_work_work_multiprocess/README.chromium
index 48bdc71b..c769c25 100644
--- a/third_party/androidx/committed/libs/androidx_work_work_multiprocess/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_work_work_multiprocess/README.chromium
@@ -1,6 +1,6 @@
 Name: WorkManager Multiprocess
 Short Name: work-multiprocess
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/work/work-multiprocess/2.12.0-SNAPSHOT/work-multiprocess-2.12.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/work/work-multiprocess/2.12.0-SNAPSHOT/work-multiprocess-2.12.0-20260225.210851-1.aar
 Version: 2.12.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_work_work_runtime/README.chromium b/third_party/androidx/committed/libs/androidx_work_work_runtime/README.chromium
index b5f1d6a..768a6a0 100644
--- a/third_party/androidx/committed/libs/androidx_work_work_runtime/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_work_work_runtime/README.chromium
@@ -1,6 +1,6 @@
 Name: WorkManager Runtime
 Short Name: work-runtime
-URL: https://androidx.dev/snapshots/builds/14936970/artifacts/repository/androidx/work/work-runtime/2.12.0-SNAPSHOT/work-runtime-2.12.0-20260225.133501-1.aar
+URL: https://androidx.dev/snapshots/builds/14939483/artifacts/repository/androidx/work/work-runtime/2.12.0-SNAPSHOT/work-runtime-2.12.0-20260225.210851-1.aar
 Version: 2.12.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/angle b/third_party/angle
index 4e62305..d5f67f1 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit 4e623053ea80f650a2bf207b60d1cd26571b37f6
+Subproject commit d5f67f17ee48eed48b6c8ec283646ccbeb0b77ed
diff --git a/third_party/blink/public/devtools_protocol/domains/Extensions.pdl b/third_party/blink/public/devtools_protocol/domains/Extensions.pdl
index d50da28..8b3da102 100644
--- a/third_party/blink/public/devtools_protocol/domains/Extensions.pdl
+++ b/third_party/blink/public/devtools_protocol/domains/Extensions.pdl
@@ -38,6 +38,28 @@
     returns
       # Extension id.
       string id
+
+  # Detailed information about an extension.
+  type ExtensionInfo extends object
+    properties
+      # Extension id.
+      string id
+      # Extension name.
+      string name
+      # Extension version.
+      string version
+      # The path from which the extension was loaded.
+      string path
+      # Extension enabled status.
+      boolean enabled
+
+  # Gets a list of all unpacked extensions.
+  # Available if the client is connected using the --remote-debugging-pipe flag
+  # and the --enable-unsafe-extension-debugging flag is set.
+  command getExtensions
+    returns
+      array of ExtensionInfo extensions
+
   # Uninstalls an unpacked extension (others not supported) from the profile.
   # Available if the client is connected using the --remote-debugging-pipe flag
   # and the --enable-unsafe-extension-debugging.
diff --git a/third_party/blink/public/mojom/ai/model_streaming_responder.mojom b/third_party/blink/public/mojom/ai/model_streaming_responder.mojom
index b6a29a0..6a6d109 100644
--- a/third_party/blink/public/mojom/ai/model_streaming_responder.mojom
+++ b/third_party/blink/public/mojom/ai/model_streaming_responder.mojom
@@ -91,5 +91,5 @@
   // Called when the context overflows when reserving the space for the newly
   // added items. It does not indicate a failure or guarantee the success.
   // Used by Prompt API only.
-  OnQuotaOverflow();
+  OnContextOverflow();
 };
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
index 475b8969..9b237f8 100644
--- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
+++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -4857,7 +4857,7 @@
   kInputParsedParentSelect = 5546,
   kInputParsedAncestorSelect = 5547,
   kCSSSelectorPseudoHasSlotted = 5548,
-  kSelectMultipleShowPopup = 5549,
+  kOBSOLETE_SelectMultipleShowPopup = 5549,
   kSharedWorkerExtendedLifetimeFeatureEnabled = 5550,
   kSharedWorkerExtendedLifetimeIsTrue = 5551,
   // The items above roughly this point are available in the M137 branch.
@@ -5111,6 +5111,8 @@
   kLanguageModel_ContextWindow = 5794,
   kLanguageModel_MeasureContextUsage = 5795,
   kV8WindowClient_Navigate_Method = 5796,
+  kLanguageModel_OnQuotaOverflow = 5797,
+  kLanguageModel_OnContextOverflow = 5798,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots. Also don't add extra
diff --git a/third_party/blink/public/platform/web_audio_bus.h b/third_party/blink/public/platform/web_audio_bus.h
index 0f52d2b..ac9ddb4 100644
--- a/third_party/blink/public/platform/web_audio_bus.h
+++ b/third_party/blink/public/platform/web_audio_bus.h
@@ -52,6 +52,11 @@
                   size_t length,
                   double sample_rate);
 
+  // Similar to Initialize, but returns false if allocation fails.
+  bool TryInitialize(unsigned number_of_channels,
+                     size_t length,
+                     double sample_rate);
+
   // ResizeSmaller() can only be called after Initialize() with a new length <=
   // the initialization length.  The data stored in the bus will remain
   // undisturbed.
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni
index b6f2e87de..12075e9 100644
--- a/third_party/blink/renderer/bindings/generated_in_core.gni
+++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -2088,6 +2088,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_sanitizerelementnamespace_string.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_sanitizerelementnamespacewithattributes_string.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_sanitizerelementnamespacewithattributes_string.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_sethtmloptions_trustedparseroptions.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_sethtmloptions_trustedparseroptions.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_sethtmlunsafeoptions_trustedparseroptions.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_sethtmlunsafeoptions_trustedparseroptions.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_string_stringsequence.cc",
diff --git a/third_party/blink/renderer/core/DEPS b/third_party/blink/renderer/core/DEPS
index 11c8bc1..445eedf 100644
--- a/third_party/blink/renderer/core/DEPS
+++ b/third_party/blink/renderer/core/DEPS
@@ -29,6 +29,7 @@
     "+cc/animation/animation_id_provider.h",
     "+cc/animation/animation_timeline.h",
     "+cc/animation/animation_trigger.h",
+    "+cc/animation/animation_trigger_delegate.h",
     "+cc/animation/filter_animation_curve.h",
     "+cc/animation/keyframe_model.h",
     "+cc/animation/scroll_offset_animation_curve.h",
diff --git a/third_party/blink/renderer/core/animation/animation_trigger.cc b/third_party/blink/renderer/core/animation/animation_trigger.cc
index 1e0244aa..a28d238 100644
--- a/third_party/blink/renderer/core/animation/animation_trigger.cc
+++ b/third_party/blink/renderer/core/animation/animation_trigger.cc
@@ -152,6 +152,20 @@
   NOTREACHED();
 }
 
+void AnimationTrigger::DestroyCompositorTrigger() {
+  if (!compositor_trigger_) {
+    return;
+  }
+
+  compositor_trigger_->SetAnimationTriggerDelegate(nullptr);
+
+  if (cc::AnimationHost* host = compositor_trigger_->GetAnimationHost()) {
+    host->RemoveTrigger(compositor_trigger_);
+  }
+
+  compositor_trigger_ = nullptr;
+}
+
 void AnimationTrigger::Dispose() {
   DestroyCompositorTrigger();
 }
@@ -323,6 +337,8 @@
     // We should tie creating a cc trigger to whether there is at least one
     // compositable animation attached, perhaps in addAnimation.
     CreateCompositorTrigger();
+    compositor_trigger_->SetAnimationTriggerDelegate(
+        static_cast<cc::AnimationTriggerDelegate*>(this));
   }
 
   if (compositor_trigger_) {
diff --git a/third_party/blink/renderer/core/animation/animation_trigger.h b/third_party/blink/renderer/core/animation/animation_trigger.h
index 3fc90939..4543f95 100644
--- a/third_party/blink/renderer/core/animation/animation_trigger.h
+++ b/third_party/blink/renderer/core/animation/animation_trigger.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ANIMATION_TRIGGER_H_
 
 #include "cc/animation/animation_trigger.h"
+#include "cc/animation/animation_trigger_delegate.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_animation_play_state.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_animation_trigger_behavior.h"
 #include "third_party/blink/renderer/core/animation/animation.h"
@@ -22,7 +23,8 @@
 class Element;
 class ExceptionState;
 
-class CORE_EXPORT AnimationTrigger : public ScriptWrappable {
+class CORE_EXPORT AnimationTrigger : public ScriptWrappable,
+                                     public cc::AnimationTriggerDelegate {
   DEFINE_WRAPPERTYPEINFO();
   USING_PRE_FINALIZER(AnimationTrigger, Dispose);
 
@@ -66,7 +68,7 @@
   void UpdateCompositorTrigger(
       const PaintArtifactCompositor* paint_artifact_compositor);
   virtual void CreateCompositorTrigger() {}
-  virtual void DestroyCompositorTrigger() {}
+  virtual void DestroyCompositorTrigger();
   cc::AnimationTrigger* CompositorTrigger() { return nullptr; }
 
   void Dispose();
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
index 4af3ef9f..0b4e85c 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -58,6 +58,7 @@
 #include "third_party/blink/renderer/core/animation/element_animations.h"
 #include "third_party/blink/renderer/core/animation/keyframe_effect.h"
 #include "third_party/blink/renderer/core/animation/pending_animations.h"
+#include "third_party/blink/renderer/core/animation/timeline_trigger.h"
 #include "third_party/blink/renderer/core/css/background_color_paint_image_generator.h"
 #include "third_party/blink/renderer/core/css/clip_path_paint_image_generator.h"
 #include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
@@ -4043,6 +4044,9 @@
             V8AnimationPlayState::Enum::kPaused);
   EXPECT_EQ(noncomposited_animation->CalculateAnimationPlayState(),
             V8AnimationPlayState::Enum::kPaused);
+  GetAnimationHostImpl()->PromoteScrollTimelinesPendingToActive();
+  double time_delta_in_seconds = 0.016;
+  double frame_count = 1;
   Compositor().BeginFrame();
 
   const cc::AnimationHost::IdToTriggerMap& trigger_map =
@@ -4055,7 +4059,12 @@
 
   // Instigate the trigger condition.
   source->scrollIntoView(nullptr);
-  Compositor().BeginFrame();
+  // We need one frame to commit the main thread scroll offset to cc and one
+  // frame to get the updated cc trigger state to main.
+  Compositor().BeginFrame(frame_count++ * time_delta_in_seconds,
+                          /*raster=*/true);
+  Compositor().BeginFrame(frame_count++ * time_delta_in_seconds,
+                          /*raster=*/true);
 
   // TODO(crbug.com/451238244): The composited animation should also be played
   // by the trigger but as cc triggers are currently not functional, the
@@ -4122,4 +4131,105 @@
   EXPECT_FLOAT_EQ(100.4f, rect.height());
 }
 
+TEST_F(CompositorAnimationTriggerTest, SyncTimelineTriggerStateOnMain) {
+  SimRequest request("https://example.com/test.html", "text/html");
+  LoadURL("https://example.com/test.html");
+  request.Complete(R"HTML(
+    <!DOCTYPE html>
+    <style>
+      @keyframes swell {
+        0% { transform: scaleX(1); }
+        50% { transform: scaleX(5); }
+        100% { transform: scaleX(1); }
+      }
+
+      .long {
+        height: 300px;
+        width: 100px;
+      }
+      .scroller {
+        overflow: scroll;
+        height: 150px;
+        width: 100px;
+      }
+
+      #target {
+        timeline-trigger: --trigger view() contain 0% contain 100%;
+        animation: swell .5s both;
+        animation-trigger: --trigger play;
+
+        background: green;
+        height: 100px;
+        width: 100px;
+      }
+    </style>
+    <div id="scroller" class="scroller">
+      <div class="long"></div>
+      <div id="target"></div>
+      <div class="long"></div>
+    </div>
+  )HTML");
+  Compositor().BeginFrame();
+
+  Element* target = GetElement("target");
+  Element* scroller = GetElement("scroller");
+
+  TimelineTrigger* trigger =
+      DynamicTo<TimelineTrigger>(target->NamedTriggers()->begin()->value.Get());
+  EXPECT_EQ(trigger->GetState(), TimelineTrigger::State::kIdle);
+
+  double scroller_size = 150;
+  double long_size = 300;
+  double target_size = 100;
+
+  double contain0 = long_size + target_size - scroller_size;
+  double contain100 = long_size;
+
+  double time_delta_in_seconds = 0.016;
+  double frame_count = 1;
+  auto commit = [&]() {
+    // For the tests that follow, we need one commit to have the compositor pick
+    // up the scroll offset update from main and another commit for the main
+    // thread trigger to sync with the updated compositor trigger.
+    Compositor().BeginFrame(frame_count++ * time_delta_in_seconds,
+                            /*raster=*/true);
+    Compositor().BeginFrame(frame_count++ * time_delta_in_seconds,
+                            /*raster=*/true);
+  };
+
+  GetAnimationHostImpl()->PromoteScrollTimelinesPendingToActive();
+
+  scroller->setScrollTop((contain0 + contain100) / 2);
+
+  // Our cc::AnimationTrigger is the source of truth for the trigger state.
+  // We shouldn't change state until a commit has occurred and we receive the
+  // state update.
+  EXPECT_EQ(trigger->GetState(), TimelineTrigger::State::kIdle);
+
+  commit();
+  EXPECT_EQ(trigger->GetState(), TimelineTrigger::State::kPrimary);
+
+  scroller->setScrollTop(contain100 + 50);
+
+  //  No commit yet, not state change expected.
+  EXPECT_EQ(trigger->GetState(), TimelineTrigger::State::kPrimary);
+  //  Post-commit, new state should be visible.
+  commit();
+  EXPECT_EQ(trigger->GetState(), TimelineTrigger::State::kInverse);
+
+  // Go back into the trigger range.
+  scroller->setScrollTop((contain0 + contain100) / 2);
+  EXPECT_EQ(trigger->GetState(), TimelineTrigger::State::kInverse);
+
+  commit();
+  EXPECT_EQ(trigger->GetState(), TimelineTrigger::State::kPrimary);
+
+  // Go back out of the trigger range.
+  scroller->setScrollTop(contain0 - 50);
+  EXPECT_EQ(trigger->GetState(), TimelineTrigger::State::kPrimary);
+
+  commit();
+  EXPECT_EQ(trigger->GetState(), TimelineTrigger::State::kInverse);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/animation/event_trigger.h b/third_party/blink/renderer/core/animation/event_trigger.h
index 7be51f0..3b0f4971 100644
--- a/third_party/blink/renderer/core/animation/event_trigger.h
+++ b/third_party/blink/renderer/core/animation/event_trigger.h
@@ -38,6 +38,10 @@
   void Trace(Visitor* visitor) const override;
 
  private:
+  // cc::AnimationTriggerDelegate implementation.
+  void NotifyActivated() override {}
+  void NotifyDeactivated() override {}
+
   void DidAddAnimation() override;
   void DidRemoveAnimation(Animation* animation) override;
   void ClearListenerIfNecessary();
diff --git a/third_party/blink/renderer/core/animation/timeline_trigger.cc b/third_party/blink/renderer/core/animation/timeline_trigger.cc
index 03e1187..02b4a384 100644
--- a/third_party/blink/renderer/core/animation/timeline_trigger.cc
+++ b/third_party/blink/renderer/core/animation/timeline_trigger.cc
@@ -185,6 +185,12 @@
     return;
   }
   GetDocument()->AttachCompositorTimeline(cc_timeline);
+
+  std::optional<CcBoundaries> cc_boundaries = ComputeCcBoundaries(cc_timeline);
+  if (!cc_boundaries) {
+    return;
+  }
+
   cc::AnimationHost* host = cc_timeline->animation_host();
   CHECK(host);
 
@@ -192,21 +198,22 @@
       host->GetScopedRefTimelineById(cc_timeline->id());
 
   scoped_refptr<cc::TimelineTrigger> cc_trigger = cc::TimelineTrigger::Create(
-      cc::AnimationIdProvider::NextAnimationTriggerId(), scopedref_cc_timeline);
+      cc::AnimationIdProvider::NextAnimationTriggerId(), scopedref_cc_timeline,
+      *cc_boundaries);
   host->AddTrigger(cc_trigger);
 
   compositor_trigger_ =
       static_cast<scoped_refptr<cc::AnimationTrigger>>(cc_trigger);
 }
 
-void TimelineTrigger::DestroyCompositorTrigger() {
-  if (compositor_trigger_) {
-    cc::AnimationHost* host = compositor_trigger_->GetAnimationHost();
-    if (host) {
-      host->RemoveTrigger(compositor_trigger_);
-    }
-    compositor_trigger_ = nullptr;
-  }
+void TimelineTrigger::NotifyActivated() {
+  state_ = State::kPrimary;
+  PerformActivate();
+}
+
+void TimelineTrigger::NotifyDeactivated() {
+  state_ = State::kInverse;
+  PerformDeactivate();
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/animation/timeline_trigger.h b/third_party/blink/renderer/core/animation/timeline_trigger.h
index a2eb7c5..460ffdf1 100644
--- a/third_party/blink/renderer/core/animation/timeline_trigger.h
+++ b/third_party/blink/renderer/core/animation/timeline_trigger.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_TIMELINE_TRIGGER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_TIMELINE_TRIGGER_H_
 
+#include "cc/animation/timeline_trigger.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_timeline_trigger_options.h"
 #include "third_party/blink/renderer/core/animation/animation_trigger.h"
 #include "third_party/blink/renderer/core/animation/scroll_timeline.h"
@@ -26,6 +27,7 @@
   using State = TimelineTriggerRange::State;
   using RangeBoundary = TimelineTriggerRange::Boundary;
   using TriggerBoundaries = TimelineTriggerRange::TriggerBoundaries;
+  using CcBoundaries = cc::TimelineTrigger::Boundaries;
 
   TimelineTrigger(TimelineTriggerRangeList* ranges,
                   Element* owning_element = nullptr);
@@ -92,7 +94,13 @@
   void Trace(Visitor* visitor) const override;
 
   void CreateCompositorTrigger() override;
-  void DestroyCompositorTrigger() override;
+
+  // TODO(crbug.com/473568234): Support multiple timelines.
+  std::optional<CcBoundaries> ComputeCcBoundaries(
+      cc::AnimationTimeline* cc_timeline) {
+    return GetRange() ? GetRange()->ComputeCcBoundaries(cc_timeline)
+                      : std::nullopt;
+  }
 
   Document* GetDocument() override {
     return Timeline() ? Timeline()->GetDocument() : nullptr;
@@ -108,6 +116,11 @@
   void DidAddAnimation() override;
   void DidRemoveAnimation(Animation* animation) override;
 
+  // These functions are called when the cc::AnimationTrigger associated with
+  // this trigger observes the related conditions on the compositor thread.
+  void NotifyActivated() override;
+  void NotifyDeactivated() override;
+
   void HandlePostTripAdd(Animation* animation,
                          Behavior activate_behavior,
                          Behavior deactivate_behavior,
diff --git a/third_party/blink/renderer/core/animation/timeline_trigger_range.cc b/third_party/blink/renderer/core/animation/timeline_trigger_range.cc
index 393e6608..5c0d29f 100644
--- a/third_party/blink/renderer/core/animation/timeline_trigger_range.cc
+++ b/third_party/blink/renderer/core/animation/timeline_trigger_range.cc
@@ -88,7 +88,7 @@
                               double default_value,
                               const ScrollTimeline& timeline,
                               const TimelineRange::ScrollOffsets& range_offsets,
-                              Element& timeline_source) {
+                              const Node& timeline_source) {
   if (offset) {
     // |range_offsets| is in physical pixels. Get the range values in CSS
     // pixels.
@@ -275,6 +275,22 @@
   return active_range_end_;
 }
 
+Node* TimelineTriggerRange::ComputeBoundariesSource(
+    const ScrollTimeline& timeline) {
+  Node* timeline_source = timeline.ComputeResolvedSource();
+  if (!timeline_source) {
+    return nullptr;
+  }
+
+  if (IsA<LayoutView>(timeline_source->GetLayoutObject())) {
+    // If the source is the root document, it isn't an "Element", so we need
+    // to work with its scrollingElement
+    timeline_source = To<Document>(timeline_source)->ScrollingElementNoLayout();
+  }
+
+  return timeline_source;
+}
+
 TimelineTriggerRange::TriggerBoundaries
 TimelineTriggerRange::ComputeTriggerBoundaries(double current_offset,
                                                Element& timeline_source,
@@ -360,24 +376,11 @@
       return std::nullopt;
     }
 
-    Node* timeline_source = timeline->ComputeResolvedSource();
-    if (!timeline_source) {
-      return std::nullopt;
-    }
+    Node* timeline_source = ComputeBoundariesSource(*timeline);
 
     current_offset = AdjustForAbsoluteZoom::AdjustScroll(
         *current_offset, *timeline_source->GetLayoutObject());
 
-    if (IsA<LayoutView>(timeline_source->GetLayoutObject())) {
-      // If the source is the root document, it isn't an "Element", so we need
-      // to work with its scrollingElement
-      timeline_source =
-          To<Document>(timeline_source)->ScrollingElementNoLayout();
-      if (!timeline_source) {
-        return std::nullopt;
-      }
-    }
-
     boundaries = ComputeTriggerBoundaries(
         *current_offset, *To<Element>(timeline_source), *timeline);
   } else {
@@ -418,6 +421,70 @@
   return new_state;
 }
 
+std::optional<TimelineTriggerRange::CcBoundaries>
+TimelineTriggerRange::ComputeCcBoundaries(cc::AnimationTimeline* cc_timeline) {
+  if (!timeline_->IsProgressBased()) {
+    // Non progress based triggers are always in a tripped state,
+    // no need to composite the trigger so we should not be in this function.
+    return std::nullopt;
+  }
+
+  ScrollTimeline* timeline =
+      DynamicTo<ScrollTimeline>(timeline_->ExposedTimeline());
+  if (!timeline) {
+    return std::nullopt;
+  }
+
+  Node* timeline_source = ComputeBoundariesSource(*timeline);
+  if (!timeline_source) {
+    return std::nullopt;
+  }
+
+  TriggerBoundaries boundaries = ComputeTriggerBoundaries(
+      /*(unused) current_offset=*/0, *To<Element>(timeline_source), *timeline);
+
+  // Blink boundaries are calculated in CSS pixels, but cc ScrollTimeline
+  // offsets are in physical pixels. So, scale the blink boundaries into
+  // physical pixels.
+  // TODO(451238244): Update boundaries whenever zoom factor changes.
+  double zoom_factor =
+      timeline_source->GetLayoutBox()->StyleRef().EffectiveZoom();
+  boundaries.activation_start = boundaries.activation_start * zoom_factor;
+  boundaries.activation_end = boundaries.activation_end * zoom_factor;
+  boundaries.active_start = boundaries.active_start * zoom_factor;
+  boundaries.active_end = boundaries.active_end * zoom_factor;
+
+  const double ms_per_pixel_multiplier =
+      cc::ScrollTimeline::kScrollTimelineMicrosecondsPerPixel;
+
+  // In cc, we evaluate "enter" and "exit" using the current time of the
+  // timeline. The current time of the timeline is measured relative to the
+  // start of the timeline's range which, in the case of a view timeline, is the
+  // start of its cover range.
+  double timeline_start_offset =
+      static_cast<cc::ScrollTimeline*>(cc_timeline)->pending_offsets()->start;
+
+  CcBoundaries cc_boundaries;
+  cc_boundaries.activation_start_time =
+      base::TimeTicks() +
+      base::Microseconds((boundaries.activation_start - timeline_start_offset) *
+                         ms_per_pixel_multiplier);
+  cc_boundaries.activation_end_time =
+      base::TimeTicks() +
+      base::Microseconds((boundaries.activation_end - timeline_start_offset) *
+                         ms_per_pixel_multiplier);
+  cc_boundaries.active_start_time =
+      base::TimeTicks() +
+      base::Microseconds((boundaries.active_start - timeline_start_offset) *
+                         ms_per_pixel_multiplier);
+  cc_boundaries.active_end_time =
+      base::TimeTicks() +
+      base::Microseconds((boundaries.active_end - timeline_start_offset) *
+                         ms_per_pixel_multiplier);
+
+  return cc_boundaries;
+}
+
 void TimelineTriggerRange::Trace(Visitor* visitor) const {
   visitor->Trace(timeline_);
   visitor->Trace(activation_range_start_);
diff --git a/third_party/blink/renderer/core/animation/timeline_trigger_range.h b/third_party/blink/renderer/core/animation/timeline_trigger_range.h
index 5b433a8..a3bc3536 100644
--- a/third_party/blink/renderer/core/animation/timeline_trigger_range.h
+++ b/third_party/blink/renderer/core/animation/timeline_trigger_range.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_TIMELINE_TRIGGER_RANGE_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_TIMELINE_TRIGGER_RANGE_H_
 
+#include "cc/animation/timeline_trigger.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_timeline_trigger_options.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_string_timelinerangeoffset.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -15,6 +16,7 @@
 class AnimationTimeline;
 class Element;
 class ExecutionContext;
+class Node;
 class ScrollTimeline;
 
 // https://drafts.csswg.org/web-animations-2/#trigger-state
@@ -39,6 +41,7 @@
  public:
   using Boundary = V8UnionStringOrTimelineRangeOffset;
   using State = TimelineTriggerState;
+  using CcBoundaries = cc::TimelineTrigger::Boundaries;
 
   TimelineTriggerRange(AnimationTimeline* timeline,
                        Boundary* activation_range_start,
@@ -73,6 +76,7 @@
     double current_offset = 0.;
   };
 
+  static Node* ComputeBoundariesSource(const ScrollTimeline& timeline);
   std::optional<TriggerBoundaries> CalculateTriggerBoundaries();
   TriggerBoundaries ComputeTriggerBoundaries(double current_offset,
                                              Element& timeline_source,
@@ -84,6 +88,9 @@
     return ComputeTriggerBoundaries(current_offset, timeline_source, timeline);
   }
 
+  std::optional<CcBoundaries> ComputeCcBoundaries(
+      cc::AnimationTimeline* cc_timeline);
+
   std::optional<State> UpdateState();
   std::optional<State> ComputeState();
   void SetRangeBoundariesForTest(Boundary* activation_start,
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
index 660b61b..e07ce0a4 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
@@ -2331,17 +2331,29 @@
         width: 100px;
         height: 100px;
       }
-      #anchor1 { left: 100px; }
-      #anchor2 { left: 150px; }
+      #anchor1 {
+        anchor-name: --anchor1;
+        left: 100px;
+      }
+      #anchor2 {
+        anchor-name: --anchor2;
+        left: 150px;
+      }
       .anchored {
         position: absolute;
         left: anchor(left);
       }
+      #a {
+        position-anchor: --anchor1;
+      }
+      #b {
+        position-anchor: --anchor2;
+      }
     </style>
     <div class=anchor id=anchor1>X</div>
     <div class=anchor id=anchor2>Y</div>
-    <div class=anchored id=a anchor=anchor1>A</div>
-    <div class=anchored id=b anchor=anchor2>B</div>
+    <div class=anchored id=a>A</div>
+    <div class=anchored id=b>B</div>
   )HTML");
 
   UpdateAllLifecyclePhasesForTest();
diff --git a/third_party/blink/renderer/core/dom/child_node.idl b/third_party/blink/renderer/core/dom/child_node.idl
index 141c069..e684c1f 100644
--- a/third_party/blink/renderer/core/dom/child_node.idl
+++ b/third_party/blink/renderer/core/dom/child_node.idl
@@ -26,4 +26,12 @@
   [Unscopable, RaisesException, CEReactions] undefined after((Node or DOMString or TrustedScript)... nodes);
   [Unscopable, RaisesException, CEReactions] undefined replaceWith((Node or DOMString or TrustedScript)... nodes);
   [Unscopable, RaisesException, CEReactions] undefined remove();
+
+  // https://github.com/whatwg/html/issues/11669
+  [RuntimeEnabled=DocumentPatching, RaisesException] void beforeHTML(DOMString html, optional (SetHTMLOptions or TrustedParserOptions) options = {});
+  [RuntimeEnabled=DocumentPatching, RaisesException] void beforeHTMLUnsafe((TrustedHTML or DOMString) html, optional (SetHTMLUnsafeOptions or TrustedParserOptions) options = {});
+  [RuntimeEnabled=DocumentPatching, RaisesException] void afterHTML(DOMString html, optional (SetHTMLOptions or TrustedParserOptions) options = {});
+  [RuntimeEnabled=DocumentPatching, RaisesException] void afterHTMLUnsafe((TrustedHTML or DOMString) html, optional (SetHTMLUnsafeOptions or TrustedParserOptions) options = {});
+  [RuntimeEnabled=DocumentPatching, RaisesException] void replaceWithHTML(DOMString html, optional (SetHTMLOptions or TrustedParserOptions) options = {});
+  [RuntimeEnabled=DocumentPatching, RaisesException] void replaceWithHTMLUnsafe((TrustedHTML or DOMString) html, optional (SetHTMLUnsafeOptions or TrustedParserOptions) options = {});
 };
diff --git a/third_party/blink/renderer/core/dom/container_node.cc b/third_party/blink/renderer/core/dom/container_node.cc
index 405b1110..3d64768 100644
--- a/third_party/blink/renderer/core/dom/container_node.cc
+++ b/third_party/blink/renderer/core/dom/container_node.cc
@@ -24,6 +24,7 @@
 #include "third_party/blink/renderer/core/dom/container_node.h"
 
 #include "third_party/blink/renderer/bindings/core/v8/v8_get_html_options.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_sethtmlunsafeoptions_trustedparseroptions.h"
 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
 #include "third_party/blink/renderer/core/css/selector_filter.h"
@@ -67,6 +68,7 @@
 #include "third_party/blink/renderer/core/html/html_stream.h"
 #include "third_party/blink/renderer/core/html/html_tag_collection.h"
 #include "third_party/blink/renderer/core/html/html_template_element.h"
+#include "third_party/blink/renderer/core/html/parser/fragment_parser_options.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/layout/layout_block_flow.h"
 #include "third_party/blink/renderer/core/layout/layout_box.h"
@@ -74,7 +76,10 @@
 #include "third_party/blink/renderer/core/layout/layout_text.h"
 #include "third_party/blink/renderer/core/layout/layout_text_combine.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
+#include "third_party/blink/renderer/core/sanitizer/sanitizer.h"
 #include "third_party/blink/renderer/core/timing/soft_navigation_heuristics.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_types_names.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
@@ -1918,8 +1923,20 @@
     ExceptionState& exception_state) {
   DEFINE_STATIC_LOCAL(AtomicString, kInterfaceName, ("streamAppendHTMLUnsafe"));
 
-  return HTMLStream::Create(script_state, this, options, kInterfaceName,
-                            exception_state);
+  return HTMLStream::Create(script_state, this,
+                            FragmentParserOptions::From(options),
+                            kInterfaceName, exception_state);
+}
+
+WritableStream* ContainerNode::streamAppendHTML(
+    ScriptState* script_state,
+    V8UnionSetHTMLOptionsOrTrustedParserOptions* options,
+    ExceptionState& exception_state) {
+  DEFINE_STATIC_LOCAL(AtomicString, kPropertyName, ("streamAppendHTML"));
+  WritableStream* stream = HTMLStream::Create(
+      script_state, this, FragmentParserOptions::From(options), kPropertyName,
+      exception_state);
+  return stream;
 }
 
 WritableStream* ContainerNode::streamHTMLUnsafe(
@@ -1927,12 +1944,118 @@
     V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions* options,
     ExceptionState& exception_state) {
   DEFINE_STATIC_LOCAL(AtomicString, kPropertyName, ("streamHTMLUnsafe"));
-  WritableStream* stream = HTMLStream::Create(script_state, this, options,
-                                              kPropertyName, exception_state);
+  WritableStream* stream = HTMLStream::Create(
+      script_state, this, FragmentParserOptions::From(options), kPropertyName,
+      exception_state);
   if (!exception_state.HadException()) {
     RemoveChildren();
   }
   return stream;
 }
 
+WritableStream* ContainerNode::streamHTML(
+    ScriptState* script_state,
+    V8UnionSetHTMLOptionsOrTrustedParserOptions* options,
+    ExceptionState& exception_state) {
+  DEFINE_STATIC_LOCAL(AtomicString, kPropertyName, ("streamHTML"));
+  WritableStream* stream = HTMLStream::Create(
+      script_state, this, FragmentParserOptions::From(options), kPropertyName,
+      exception_state);
+  if (!exception_state.HadException()) {
+    RemoveChildren();
+  }
+  return stream;
+}
+
+void ContainerNode::appendHTML(
+    const String& html,
+    V8UnionSetHTMLOptionsOrTrustedParserOptions* options,
+    ExceptionState& exception_state) {
+  CHECK(IsElementNode() || IsShadowRoot());
+  InsertHTMLBefore(nullptr, html,
+                   blink::GetFragmentParserConfig(
+                       Sanitizer::Mode::kSafe,
+                       IsElementNode() ? trusted_types_names::kElement
+                                       : trusted_types_names::kShadowRoot,
+                       trusted_types_names::kAppendHTML, this),
+                   FragmentParserOptions::From(options), exception_state);
+}
+
+void ContainerNode::appendHTMLUnsafe(
+    const V8UnionStringOrTrustedHTML* html,
+    V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions* options,
+    ExceptionState& exception_state) {
+  CHECK(IsElementNode() || IsShadowRoot());
+
+  const FragmentParserConfig config = blink::GetFragmentParserConfig(
+      Sanitizer::Mode::kUnsafe,
+      IsElementNode() ? trusted_types_names::kElement
+                      : trusted_types_names::kShadowRoot,
+      trusted_types_names::kAppendHTMLUnsafe, this);
+  InsertHTMLBefore(nullptr,
+                   TrustedTypesCheckForHTML(
+                       html, GetExecutionContext(), config.interface_name,
+                       config.property_name, exception_state),
+                   config, FragmentParserOptions::From(options),
+                   exception_state);
+}
+
+void ContainerNode::prependHTML(
+    const String& html,
+    V8UnionSetHTMLOptionsOrTrustedParserOptions* options,
+    ExceptionState& exception_state) {
+  CHECK(IsElementNode() || IsShadowRoot());
+  InsertHTMLBefore(firstChild(), html,
+                   blink::GetFragmentParserConfig(
+                       Sanitizer::Mode::kSafe,
+                       IsElementNode() ? trusted_types_names::kElement
+                                       : trusted_types_names::kShadowRoot,
+                       trusted_types_names::kPrependHTML, this),
+                   FragmentParserOptions::From(options), exception_state);
+}
+
+void ContainerNode::prependHTMLUnsafe(
+    const V8UnionStringOrTrustedHTML* html,
+    V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions* options,
+    ExceptionState& exception_state) {
+  const FragmentParserConfig config = blink::GetFragmentParserConfig(
+      Sanitizer::Mode::kUnsafe,
+      IsElementNode() ? trusted_types_names::kElement
+                      : trusted_types_names::kShadowRoot,
+      trusted_types_names::kPrependHTMLUnsafe, this);
+  InsertHTMLBefore(firstChild(),
+                   TrustedTypesCheckForHTML(
+                       html, GetExecutionContext(), config.interface_name,
+                       config.property_name, exception_state),
+                   config, FragmentParserOptions::From(options),
+                   exception_state);
+}
+
+void ContainerNode::InsertHTMLBefore(Node* ref_child,
+                                     const String& html,
+                                     const FragmentParserConfig& config,
+                                     const FragmentParserOptions& options,
+                                     ExceptionState& exception_state) {
+  if (exception_state.HadException()) {
+    return;
+  }
+  if (DocumentFragment* fragment =
+          ParseHTMLFragment(html, config, options, exception_state)) {
+    InsertBefore(fragment, ref_child);
+  }
+}
+void ContainerNode::ReplaceChildWithHTML(Node* ref_child,
+                                         const String& html,
+                                         const FragmentParserConfig& config,
+                                         const FragmentParserOptions& options,
+                                         ExceptionState& exception_state) {
+  if (exception_state.HadException()) {
+    return;
+  }
+  if (DocumentFragment* fragment =
+          ParseHTMLFragment(html, config, options, exception_state)) {
+    ReplaceChild(fragment, ref_child);
+  }
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/container_node.h b/third_party/blink/renderer/core/dom/container_node.h
index a56fb73c..72a3917 100644
--- a/third_party/blink/renderer/core/dom/container_node.h
+++ b/third_party/blink/renderer/core/dom/container_node.h
@@ -32,19 +32,24 @@
 #include "third_party/blink/renderer/core/dom/node.h"
 #include "third_party/blink/renderer/core/dom/static_node_list.h"
 #include "third_party/blink/renderer/core/html/collection_type.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
 #include "third_party/blink/renderer/platform/heap/heap_traits.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
 
 class Element;
 class ExceptionState;
+class FragmentParserConfig;
+class FragmentParserOptions;
 class GetHTMLOptions;
 class HTMLCollection;
 class RadioNodeList;
 class ScriptState;
 class V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions;
+class V8UnionSetHTMLOptionsOrTrustedParserOptions;
 class StyleRecalcContext;
 class WhitespaceAttacher;
 class WritableStream;
@@ -403,6 +408,40 @@
       ScriptState*,
       V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions*,
       ExceptionState&);
+  WritableStream* streamHTML(ScriptState*,
+                             V8UnionSetHTMLOptionsOrTrustedParserOptions*,
+                             ExceptionState&);
+  WritableStream* streamAppendHTML(ScriptState*,
+                                   V8UnionSetHTMLOptionsOrTrustedParserOptions*,
+                                   ExceptionState&);
+  void appendHTML(const String& html,
+                  V8UnionSetHTMLOptionsOrTrustedParserOptions* options,
+                  ExceptionState& exception_state);
+
+  void appendHTMLUnsafe(
+      const V8UnionStringOrTrustedHTML* html,
+      V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions* options,
+      ExceptionState& exception_state);
+
+  void prependHTML(const String& html,
+                   V8UnionSetHTMLOptionsOrTrustedParserOptions* options,
+                   ExceptionState& exception_state);
+
+  void prependHTMLUnsafe(
+      const V8UnionStringOrTrustedHTML* html,
+      V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions* options,
+      ExceptionState& exception_state);
+
+  void InsertHTMLBefore(Node* ref_child,
+                        const String& html,
+                        const FragmentParserConfig&,
+                        const FragmentParserOptions&,
+                        ExceptionState&);
+  void ReplaceChildWithHTML(Node* ref_child,
+                            const String& html,
+                            const FragmentParserConfig&,
+                            const FragmentParserOptions&,
+                            ExceptionState&);
 
   // DocumentOrElementEventHandlers:
   // These event listeners are only actually web-exposed on interfaces that
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 96c1bc5..9cd1074 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -263,6 +263,7 @@
 #include "third_party/blink/renderer/core/html/html_unknown_element.h"
 #include "third_party/blink/renderer/core/html/media/lazy_load_media_observer.h"
 #include "third_party/blink/renderer/core/html/nesting_level_incrementer.h"
+#include "third_party/blink/renderer/core/html/parser/fragment_parser_options.h"
 #include "third_party/blink/renderer/core/html/parser/html_document_parser.h"
 #include "third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.h"
 #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
@@ -336,6 +337,7 @@
 #include "third_party/blink/renderer/core/resize_observer/resize_observer_entry.h"
 #include "third_party/blink/renderer/core/resize_observer/resize_observer_size.h"
 #include "third_party/blink/renderer/core/route_matching/route_map.h"
+#include "third_party/blink/renderer/core/sanitizer/sanitizer.h"
 #include "third_party/blink/renderer/core/sanitizer/sanitizer_api.h"
 #include "third_party/blink/renderer/core/script/detect_javascript_frameworks.h"
 #include "third_party/blink/renderer/core/script/script_runner.h"
@@ -5335,7 +5337,7 @@
 
   if (!request.ReadOnly()) {
     UpdateHoverActiveState(request.Active(), !request.Move(),
-                           result.InnerElement());
+                           result.InnerPossiblyPseudoElement());
   }
 
   return MouseEventWithHitTestResults(event, location, result);
@@ -10137,8 +10139,10 @@
     return nullptr;
   }
   Document* doc = parseHTMLInternal(context, compliant_html, exception_state);
-  SanitizerAPI::SanitizeUnsafeInternal(
-      /*context_element*/ doc, /*root_element*/ doc, options, exception_state);
+  SanitizerAPI::SanitizeInternal(Sanitizer::Mode::kUnsafe,
+                                 /*context_element*/ doc, /*root_element*/ doc,
+                                 FragmentParserOptions(options),
+                                 exception_state);
   return doc;
 }
 
@@ -10149,8 +10153,10 @@
                               ExceptionState& exception_state) {
   CHECK(RuntimeEnabledFeatures::SanitizerAPIEnabled());
   Document* doc = parseHTMLInternal(context, html, exception_state);
-  SanitizerAPI::SanitizeSafeInternal(
-      /*context_element*/ doc, /*root_element*/ doc, options, exception_state);
+  SanitizerAPI::SanitizeInternal(Sanitizer::Mode::kSafe,
+                                 /*context_element*/ doc, /*root_element*/ doc,
+                                 FragmentParserOptions(options),
+                                 exception_state);
   return doc;
 }
 
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index ef748cc..7bd5375 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -50,6 +50,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_scroll_container.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_scroll_into_view_options.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_scroll_to_options.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_set_html_options.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_set_html_unsafe_options.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_shadow_root_init.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_timeline_range.h"
@@ -57,6 +58,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_boolean_scrollintoviewoptions.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_keyframeanimationoptions_unrestricteddouble.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_keyframeeffectoptions_unrestricteddouble.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_sethtmlunsafeoptions_trustedparseroptions.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_string_timelinerangeoffset.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_stringlegacynulltoemptystring_trustedhtml.h"
 #include "third_party/blink/renderer/core/accessibility/ax_context.h"
@@ -110,6 +112,7 @@
 #include "third_party/blink/renderer/core/dom/container_node.h"
 #include "third_party/blink/renderer/core/dom/dataset_dom_string_map.h"
 #include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/document_fragment.h"
 #include "third_party/blink/renderer/core/dom/document_lifecycle.h"
 #include "third_party/blink/renderer/core/dom/dom_token_list.h"
 #include "third_party/blink/renderer/core/dom/element_data_cache.h"
@@ -173,7 +176,6 @@
 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
 #include "third_party/blink/renderer/core/geometry/dom_rect.h"
 #include "third_party/blink/renderer/core/geometry/dom_rect_list.h"
-#include "third_party/blink/renderer/core/html/anchor_element_observer.h"
 #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
 #include "third_party/blink/renderer/core/html/custom/custom_element.h"
 #include "third_party/blink/renderer/core/html/custom/custom_element_registry.h"
@@ -210,6 +212,7 @@
 #include "third_party/blink/renderer/core/html/html_template_element.h"
 #include "third_party/blink/renderer/core/html/media/html_video_element.h"
 #include "third_party/blink/renderer/core/html/nesting_level_incrementer.h"
+#include "third_party/blink/renderer/core/html/parser/fragment_parser_options.h"
 #include "third_party/blink/renderer/core/html/parser/html_element_stack.h"
 #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
 #include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
@@ -244,6 +247,7 @@
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
 #include "third_party/blink/renderer/core/resize_observer/resize_observer_size.h"
+#include "third_party/blink/renderer/core/sanitizer/sanitizer.h"
 #include "third_party/blink/renderer/core/sanitizer/sanitizer_api.h"
 #include "third_party/blink/renderer/core/scroll/scroll_into_view_util.h"
 #include "third_party/blink/renderer/core/scroll/scroll_types.h"
@@ -260,6 +264,8 @@
 #include "third_party/blink/renderer/core/svg/svg_use_element.h"
 #include "third_party/blink/renderer/core/svg_names.h"
 #include "third_party/blink/renderer/core/timing/soft_navigation_heuristics.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_parser_options.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_types_names.h"
 #include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
 #include "third_party/blink/renderer/core/view_transition/view_transition_pseudo_element_base.h"
 #include "third_party/blink/renderer/core/view_transition/view_transition_supplement.h"
@@ -498,9 +504,6 @@
   if (name == html_names::kPopovertargetAttr) {
     return true;
   }
-  if (name == html_names::kAnchorAttr) {
-    return true;
-  }
   if (name == html_names::kCommandforAttr) {
     return true;
   }
@@ -2039,26 +2042,6 @@
   ContainerNode::DefaultEventHandler(event);
 }
 
-Element* Element::anchorElement() const {
-  if (!RuntimeEnabledFeatures::HTMLAnchorAttributeEnabled()) {
-    return nullptr;
-  }
-  return GetElementAttributeResolvingReferenceTarget(html_names::kAnchorAttr);
-}
-
-// For JavaScript binding, return the anchor element without resolving the
-// reference target, to avoid exposing shadow root content to JS.
-Element* Element::anchorElementForBinding() const {
-  CHECK(RuntimeEnabledFeatures::HTMLAnchorAttributeEnabled());
-  return GetElementAttribute(html_names::kAnchorAttr);
-}
-
-void Element::setAnchorElementForBinding(Element* new_element) {
-  CHECK(RuntimeEnabledFeatures::HTMLAnchorAttributeEnabled());
-  SetElementAttribute(html_names::kAnchorAttr, new_element);
-  EnsureAnchorElementObserver().Notify();
-}
-
 inline void Element::SynchronizeAttribute(const QualifiedName& name) const {
   if (!HasElementData()) {
     return;
@@ -3893,11 +3876,7 @@
       StyleAttributeChanged(params.new_value, params.reason);
       SoftNavigationHeuristics::ModifiedAttribute(this, name);
     } else if (IsPresentationAttribute(name)) {
-      if (name == html_names::kAnchorAttr) {
-        if (RuntimeEnabledFeatures::HTMLAnchorAttributeEnabled()) {
-          EnsureAnchorElementObserver().Notify();
-        }
-      } else if (name == html_names::kHiddenAttr) {
+      if (name == html_names::kHiddenAttr) {
         if (params.new_value == keywords::kUntilFound) {
           EnsureDisplayLockContext().SetIsHiddenUntilFoundElement(true);
         } else if (DisplayLockContext* context = GetDisplayLockContext()) {
@@ -4224,10 +4203,6 @@
     SetIsCanvasOrInCanvasSubtree(true);
   }
 
-  if (AnchorElementObserver* observer = GetAnchorElementObserver()) {
-    observer->Notify();
-  }
-
   if (!insertion_point.IsInTreeScope()) {
     return kInsertionDone;
   }
@@ -4515,10 +4490,6 @@
     frame->GetEventHandler().ElementRemoved(this);
   }
 
-  if (AnchorElementObserver* observer = GetAnchorElementObserver()) {
-    observer->Notify();
-  }
-
   // Removing an element means that we should remove this overscroll area,
   // since we won't visit this node during style when we typically would do
   // this. There may be another element with the same ID that we discover
@@ -9205,82 +9176,82 @@
       V8UnionStringLegacyNullToEmptyStringOrTrustedHTML>(GetOuterHTMLString());
 }
 
+namespace {
+CustomElementRegistry* CustomElementRegistryForInnerHTML(Element* element) {
+  // Use null registry to create fragment if the context element is a
+  // template element as the container of the document fragment will be a
+  // document fragment without browsing context.
+  auto* template_element = DynamicTo<HTMLTemplateElement>(*element);
+  CustomElementRegistry* registry =
+      element->GetDocument().customElementRegistry();
+  if (RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled()) {
+    registry = template_element ? nullptr : element->customElementRegistry();
+  }
+  return registry;
+}
+}  // namespace
+
 void Element::SetInnerHTMLInternal(
     const String& html,
-    ParseDeclarativeShadowRoots parse_declarative_shadows,
-    ForceHtml force_html,
-    std::variant<std::monostate, SetHTMLOptions*, SetHTMLUnsafeOptions*>
-        options,
+    FragmentParserConfig::ParseDeclarativeShadowRoots parse_declarative_shadows,
+    FragmentParserConfig::ForceHtml force_html,
+    Sanitizer::Mode sanitizer_mode,
+    const FragmentParserOptions& options,
+    const AtomicString& property_name,
     ExceptionState& exception_state) {
+  if (exception_state.HadException()) {
+    return;
+  }
   if (html.empty() && !HasNonInBodyInsertionMode()) {
     setTextContent(html);
-  } else {
-    // Use null registry to create fragment if the context element is a
-    // template element as the container of the document fragment will be a
-    // document fragment without browsing context.
-    auto* template_element = DynamicTo<HTMLTemplateElement>(*this);
-    CustomElementRegistry* registry = GetDocument().customElementRegistry();
-    if (RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled()) {
-      registry = template_element ? nullptr : customElementRegistry();
-    }
-    const ParserContentPolicy content_policy =
-        (RuntimeEnabledFeatures::SetHTMLCanRunScriptsEnabled() &&
-         std::holds_alternative<SetHTMLUnsafeOptions*>(options) &&
-         std::get<SetHTMLUnsafeOptions*>(options)->runScripts())
-            ? kAllowScriptingContentAndDoNotMarkAlreadyStarted
-            : kAllowScriptingContent;
-
-    if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML(
-            html, this, content_policy, parse_declarative_shadows, force_html,
-            std::holds_alternative<std::monostate>(options)
-                ? ForceInertTemplate::kDontForce
-                : ForceInertTemplate::kForce,
-            registry, exception_state)) {
-      if (std::holds_alternative<SetHTMLOptions*>(options)) {
-        CHECK(RuntimeEnabledFeatures::SanitizerAPIEnabled());
-        SanitizerAPI::SanitizeSafeInternal(this, fragment,
-                                           std::get<SetHTMLOptions*>(options),
-                                           exception_state);
-      } else if (std::holds_alternative<SetHTMLUnsafeOptions*>(options)) {
-        CHECK(RuntimeEnabledFeatures::SanitizerAPIEnabled());
-        SanitizerAPI::SanitizeUnsafeInternal(
-            this, fragment, std::get<SetHTMLUnsafeOptions*>(options),
-            exception_state);
-      } else {
-        CHECK(std::holds_alternative<std::monostate>(options));
-        // No options; nothing to do.
-      }
-      ContainerNode* container = this;
-      if (template_element) {
-        container = template_element->content();
-      }
-      ReplaceChildrenWithFragment(container, fragment, exception_state);
-    }
+    return;
   }
+
+  DocumentFragment* fragment =
+      ParseHTMLFragment(html,
+                        {.sanitizer_mode = sanitizer_mode,
+                         .parse_declarative_shadows = parse_declarative_shadows,
+                         .force_html = force_html,
+                         .interface_name = trusted_types_names::kElement,
+                         .property_name = property_name,
+                         .context_element = this,
+                         .registry = CustomElementRegistryForInnerHTML(this)},
+                        options, exception_state);
+
+  if (!fragment) {
+    return;
+  }
+
+  ContainerNode* container = this;
+  if (auto* template_element = DynamicTo<HTMLTemplateElement>(this)) {
+    container = template_element->content();
+  }
+  ReplaceChildrenWithFragment(container, fragment, exception_state);
 }
 
 void Element::SetInnerHTMLWithoutTrustedTypes(const String& html,
                                               ExceptionState& exception_state) {
-  SetInnerHTMLInternal(html, ParseDeclarativeShadowRoots::kDontParse,
-                       ForceHtml::kDontForce, std::monostate{},
-                       exception_state);
+  SetInnerHTMLInternal(
+      html, FragmentParserConfig::ParseDeclarativeShadowRoots::kDontParse,
+      FragmentParserConfig::ForceHtml::kDontForce, Sanitizer::Mode::kUnsafe,
+      FragmentParserOptions(), trusted_types_names::kInnerHTML,
+      exception_state);
 }
 
 void Element::setInnerHTML(
     const V8UnionStringLegacyNullToEmptyStringOrTrustedHTML* html,
     ExceptionState& exception_state) {
   probe::BreakableLocation(GetExecutionContext(), "Element.setInnerHTML");
-  String compliant_html = TrustedTypesCheckForHTML(
-      html, GetExecutionContext(), trusted_types_names::kElement,
-      trusted_types_names::kInnerHTML, exception_state);
+  SetInnerHTMLWithoutTrustedTypes(
+      CheckTrustedTypes(html, trusted_types_names::kInnerHTML, exception_state),
+      exception_state);
+}
+
+void Element::SetOuterHTMLInternal(const String& html,
+                                   ExceptionState& exception_state) {
   if (exception_state.HadException()) {
     return;
   }
-  SetInnerHTMLWithoutTrustedTypes(compliant_html, exception_state);
-}
-
-void Element::SetOuterHTMLWithoutTrustedTypes(const String& html,
-                                              ExceptionState& exception_state) {
   Node* p = parentNode();
   if (!p) {
     exception_state.ThrowDOMException(
@@ -9301,15 +9272,20 @@
   Node* prev = previousSibling();
   Node* next = nextSibling();
 
-  DocumentFragment* fragment = CreateFragmentForInnerOuterHTML(
-      html, parent, kAllowScriptingContent,
-      ParseDeclarativeShadowRoots::kDontParse, ForceHtml::kDontForce,
-      ForceInertTemplate::kDontForce,
-      RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled()
-          ? customElementRegistry()
-          : GetDocument().customElementRegistry(),
-      exception_state);
-  if (exception_state.HadException()) {
+  DocumentFragment* fragment = ParseHTMLFragment(
+      html,
+      {
+          .interface_name = trusted_types_names::kElement,
+          .property_name = trusted_types_names::kOuterHTML,
+          .context_element = parent,
+          .registry =
+              RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled()
+                  ? customElementRegistry()
+                  : GetDocument().customElementRegistry(),
+      },
+      FragmentParserOptions(), exception_state);
+
+  if (!fragment) {
     return;
   }
 
@@ -9334,16 +9310,17 @@
   }
 }
 
+void Element::SetOuterHTMLWithoutTrustedTypes(const String& html,
+                                              ExceptionState& exception_state) {
+  SetOuterHTMLInternal(html, exception_state);
+}
+
 void Element::setOuterHTML(
     const V8UnionStringLegacyNullToEmptyStringOrTrustedHTML* html,
     ExceptionState& exception_state) {
-  String compliant_html = TrustedTypesCheckForHTML(
-      html, GetExecutionContext(), trusted_types_names::kElement,
-      trusted_types_names::kOuterHTML, exception_state);
-  if (exception_state.HadException()) {
-    return;
-  }
-  SetOuterHTMLWithoutTrustedTypes(compliant_html, exception_state);
+  SetOuterHTMLInternal(
+      CheckTrustedTypes(html, trusted_types_names::kOuterHTML, exception_state),
+      exception_state);
 }
 
 // Step 4 of http://domparsing.spec.whatwg.org/#insertadjacenthtml()
@@ -9546,10 +9523,12 @@
   InsertAdjacent(where, GetDocument().createTextNode(text), exception_state);
 }
 
-void Element::InsertAdjacentHTMLWithoutTrustedTypes(
-    const String& where,
-    const String& markup,
-    ExceptionState& exception_state) {
+void Element::InsertAdjacentHTMLInternal(const String& where,
+                                         const String& html,
+                                         ExceptionState& exception_state) {
+  if (exception_state.HadException()) {
+    return;
+  }
   Node* context_node = ContextNodeForInsertion(where, this, exception_state);
   if (!context_node) {
     return;
@@ -9567,30 +9546,37 @@
   }
 
   // Step 3 of http://domparsing.spec.whatwg.org/#insertadjacenthtml()
-  DocumentFragment* fragment = CreateFragmentForInnerOuterHTML(
-      markup, context_element, kAllowScriptingContent,
-      ParseDeclarativeShadowRoots::kDontParse, ForceHtml::kDontForce,
-      ForceInertTemplate::kDontForce,
-      RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled()
-          ? customElementRegistry()
-          : GetDocument().customElementRegistry(),
-      exception_state);
-  if (!fragment) {
-    return;
+  if (DocumentFragment* fragment = ParseHTMLFragment(
+          html,
+          {
+              .interface_name = trusted_types_names::kElement,
+              .property_name = trusted_types_names::kInsertAdjacentHTML,
+              .context_element = context_element,
+              .registry =
+                  RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled()
+                      ? customElementRegistry()
+                      : GetDocument().customElementRegistry(),
+          },
+          FragmentParserOptions(), exception_state)) {
+    InsertAdjacent(where, fragment, exception_state);
   }
-  InsertAdjacent(where, fragment, exception_state);
+}
+
+void Element::InsertAdjacentHTMLWithoutTrustedTypesForTesting(
+    const String& where,
+    const String& markup,
+    ExceptionState& exception_state) {
+  InsertAdjacentHTMLInternal(where, markup, exception_state);
 }
 
 void Element::insertAdjacentHTML(const String& where,
                                  const V8UnionStringOrTrustedHTML* html,
                                  ExceptionState& exception_state) {
-  String compliant_html = TrustedTypesCheckForHTML(
-      html, GetExecutionContext(), trusted_types_names::kElement,
-      trusted_types_names::kInsertAdjacentHTML, exception_state);
-  if (exception_state.HadException()) {
-    return;
-  }
-  InsertAdjacentHTMLWithoutTrustedTypes(where, compliant_html, exception_state);
+  InsertAdjacentHTMLInternal(
+      where,
+      CheckTrustedTypes(html, trusted_types_names::kInsertAdjacentHTML,
+                        exception_state),
+      exception_state);
 }
 
 void Element::setPointerCapture(PointerId pointer_id,
@@ -10323,13 +10309,7 @@
       if (element->NeedsReattachLayoutTree() &&
           !PseudoElementLayoutObjectIsNeeded(
               pseudo_id, element->GetComputedStyle(), this)) {
-        // RecalcStyle will have cancelled any CSS animations on the element
-        // if the underlying base style had display:none. An animation to
-        // display: none keeps the element and the animation alive.
-        if (!element->HasAnimations()) {
-          generate_pseudo = false;
-        }
-
+        generate_pseudo = false;
         // If the content property is relying on attr() we should add the
         // originating element's ComputedStyle to the pseudo-element style
         // cache, so that when attribute value changes it will force style
@@ -10348,9 +10328,8 @@
       element = nullptr;
     }
 
-    // A pseudo-element without computed style can only exist if being
-    // kept alive by an animation.
-    DCHECK(!element || element->GetComputedStyle() || element->HasAnimations());
+    // A pseudo-element without computed style should not exist.
+    DCHECK(!element || element->GetComputedStyle());
   }
 
   return element;
@@ -10591,11 +10570,8 @@
   }
 
   for (PseudoElement* pseudo_element : rare_data->GetPseudoElements()) {
-    if (const ComputedStyle* pseudo_element_style =
-            pseudo_element->GetComputedStyle()) {
-      if (pseudo_element_style->GetCounterDirectives()) {
-        return true;
-      }
+    if (pseudo_element->GetComputedStyle()->GetCounterDirectives()) {
+      return true;
     }
   }
 
@@ -10650,11 +10626,8 @@
   }
 
   for (PseudoElement* pseudo_element : rare_data->GetPseudoElements()) {
-    if (const ComputedStyle* pseudo_element_style =
-            pseudo_element->GetComputedStyle()) {
-      if (func(*pseudo_element_style)) {
-        return true;
-      }
+    if (func(*pseudo_element->GetComputedStyle())) {
+      return true;
     }
   }
 
@@ -13335,23 +13308,7 @@
   return false;
 }
 
-AnchorElementObserver* Element::GetAnchorElementObserver() const {
-  if (const ElementRareDataVector* data = RareData()) {
-    return data->GetAnchorElementObserver();
-  }
-  return nullptr;
-}
-
-AnchorElementObserver& Element::EnsureAnchorElementObserver() {
-  DCHECK(RuntimeEnabledFeatures::HTMLAnchorAttributeEnabled());
-  return UnpackAndRefresh(EnsureRareData().EnsureAnchorElementObserver(this));
-}
-
 Element* Element::ImplicitAnchorElement() const {
-  if (Element* anchor = anchorElement()) {
-    DCHECK(RuntimeEnabledFeatures::HTMLAnchorAttributeEnabled());
-    return anchor;
-  }
   if (const HTMLElement* html_element = DynamicTo<HTMLElement>(this)) {
     if (Element* internal_anchor = html_element->implicitAnchor()) {
       return internal_anchor;
@@ -13476,43 +13433,75 @@
     const String& html,
     ExceptionState& exception_state) {
   UseCounter::Count(GetDocument(), WebFeature::kHTMLUnsafeMethods);
-  SetInnerHTMLInternal(html, ParseDeclarativeShadowRoots::kParse,
-                       ForceHtml::kForce, std::monostate{}, exception_state);
+  SetInnerHTMLInternal(
+      html, FragmentParserConfig::ParseDeclarativeShadowRoots::kParse,
+      FragmentParserConfig::ForceHtml::kForce, Sanitizer::Mode::kUnsafe,
+      FragmentParserOptions(), trusted_types_names::kSetHTMLUnsafe,
+      exception_state);
 }
 
 void Element::setHTMLUnsafe(const V8UnionStringOrTrustedHTML* html,
                             ExceptionState& exception_state) {
   UseCounter::Count(GetDocument(), WebFeature::kHTMLUnsafeMethods);
-  String compliant_html = TrustedTypesCheckForHTML(
-      html, GetExecutionContext(), trusted_types_names::kElement,
-      trusted_types_names::kSetHTMLUnsafe, exception_state);
-  if (exception_state.HadException()) {
-    return;
-  }
-  SetInnerHTMLInternal(compliant_html, ParseDeclarativeShadowRoots::kParse,
-                       ForceHtml::kForce, std::monostate{}, exception_state);
+  SetInnerHTMLInternal(
+      CheckTrustedTypes(html, trusted_types_names::kSetHTMLUnsafe,
+                        exception_state),
+      FragmentParserConfig::ParseDeclarativeShadowRoots::kParse,
+      FragmentParserConfig::ForceHtml::kForce, Sanitizer::Mode::kUnsafe,
+      FragmentParserOptions(), trusted_types_names::kSetHTMLUnsafe,
+      exception_state);
 }
 
+// TODO(nrosenthal): merge these calls once all the flags are merged.
 void Element::setHTMLUnsafe(const V8UnionStringOrTrustedHTML* html,
                             SetHTMLUnsafeOptions* options,
                             ExceptionState& exception_state) {
   CHECK(RuntimeEnabledFeatures::SanitizerAPIEnabled());
-  String compliant_html = TrustedTypesCheckForHTML(
-      html, GetExecutionContext(), trusted_types_names::kElement,
-      trusted_types_names::kSetHTMLUnsafe, exception_state);
-  if (exception_state.HadException()) {
-    return;
-  }
-  SetInnerHTMLInternal(compliant_html, ParseDeclarativeShadowRoots::kParse,
-                       ForceHtml::kForce, options, exception_state);
+  UseCounter::Count(GetDocument(), WebFeature::kHTMLUnsafeMethods);
+
+  SetInnerHTMLInternal(
+      CheckTrustedTypes(html, trusted_types_names::kSetHTMLUnsafe,
+                        exception_state),
+      FragmentParserConfig::ParseDeclarativeShadowRoots::kParse,
+      FragmentParserConfig::ForceHtml::kForce, Sanitizer::Mode::kUnsafe,
+      FragmentParserOptions(options), trusted_types_names::kSetHTMLUnsafe,
+      exception_state);
+}
+
+void Element::setHTMLUnsafe(const V8UnionStringOrTrustedHTML* html,
+                            TrustedParserOptions* options,
+                            ExceptionState& exception_state) {
+  CHECK(RuntimeEnabledFeatures::DocumentPatchingEnabled());
+  UseCounter::Count(GetDocument(), WebFeature::kHTMLUnsafeMethods);
+  SetInnerHTMLInternal(
+      CheckTrustedTypes(html, trusted_types_names::kSetHTMLUnsafe,
+                        exception_state),
+      FragmentParserConfig::ParseDeclarativeShadowRoots::kParse,
+      FragmentParserConfig::ForceHtml::kForce, Sanitizer::Mode::kUnsafe,
+      FragmentParserOptions(options), trusted_types_names::kSetHTMLUnsafe,
+      exception_state);
 }
 
 void Element::setHTML(const String& html,
                       SetHTMLOptions* options,
                       ExceptionState& exception_state) {
   CHECK(RuntimeEnabledFeatures::SanitizerAPIEnabled());
-  SetInnerHTMLInternal(html, ParseDeclarativeShadowRoots::kParse,
-                       ForceHtml::kForce, options, exception_state);
+  SetInnerHTMLInternal(
+      html, FragmentParserConfig::ParseDeclarativeShadowRoots::kParse,
+      FragmentParserConfig::ForceHtml::kForce, Sanitizer::Mode::kSafe,
+      FragmentParserOptions(options), trusted_types_names::kSetHTML,
+      exception_state);
+}
+
+void Element::setHTML(const String& html,
+                      TrustedParserOptions* options,
+                      ExceptionState& exception_state) {
+  CHECK(RuntimeEnabledFeatures::SanitizerAPIEnabled());
+  SetInnerHTMLInternal(
+      html, FragmentParserConfig::ParseDeclarativeShadowRoots::kParse,
+      FragmentParserConfig::ForceHtml::kForce, Sanitizer::Mode::kSafe,
+      FragmentParserOptions(options), trusted_types_names::kSetHTML,
+      exception_state);
 }
 
 void Element::SetNamedTriggers(NamedAnimationTriggerMap&& named_triggers) {
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index 447d499..51dbbdb 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -53,8 +53,10 @@
 #include "third_party/blink/renderer/core/dom/names_map.h"
 #include "third_party/blink/renderer/core/dom/node.h"
 #include "third_party/blink/renderer/core/dom/whitespace_attacher.h"
+#include "third_party/blink/renderer/core/html/parser/fragment_parser_options.h"
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/style/computed_style_constants.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_types_names.h"
 #include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/transform_view.h"
@@ -79,7 +81,6 @@
 
 namespace blink {
 
-class AnchorElementObserver;
 class AnchorPositionScrollData;
 class Animation;
 class AnimationTrigger;
@@ -150,6 +151,7 @@
 class StyleRecalcContext;
 class StyleScopeData;
 class TextVisitor;
+class TrustedParserOptions;
 class V8UnionBooleanOrScrollIntoViewOptions;
 class V8UnionKeyframeAnimationOptionsOrUnrestrictedDouble;
 class V8UnionStringLegacyNullToEmptyStringOrTrustedHTML;
@@ -294,19 +296,6 @@
           Document*,
           ConstructionType = kCreateElement);
 
-  // ParseDeclarativeShadowRoots specifies whether declarative shadow roots
-  // should be parsed by the HTML parser.
-  enum class ParseDeclarativeShadowRoots {
-    kDontParse = 0,
-    kParse = 1,
-  };
-  // ForceHtml specifies whether the HTML parser should be used when parsing
-  // markup even if we are in an XML document.
-  enum class ForceHtml {
-    kDontForce = 0,
-    kForce = 1,
-  };
-
   // Animatable implementation.
   // https://drafts.csswg.org/web-animations-1/#the-animatable-interface-mixin
 
@@ -1404,9 +1393,9 @@
   void insertAdjacentText(const String& where,
                           const String& text,
                           ExceptionState&);
-  void InsertAdjacentHTMLWithoutTrustedTypes(const String& where,
-                                             const String& html,
-                                             ExceptionState&);
+  void InsertAdjacentHTMLWithoutTrustedTypesForTesting(const String& where,
+                                                       const String& html,
+                                                       ExceptionState&);
   void insertAdjacentHTML(const String& where,
                           const V8UnionStringOrTrustedHTML* html,
                           ExceptionState&);
@@ -1417,7 +1406,7 @@
                                        ExceptionState& = ASSERT_NO_EXCEPTION);
   void SetOuterHTMLWithoutTrustedTypes(const String&,
                                        ExceptionState& = ASSERT_NO_EXCEPTION);
-
+  void SetOuterHTMLInternal(const String&, ExceptionState&);
   V8UnionStringLegacyNullToEmptyStringOrTrustedHTML* innerHTML() const;
   V8UnionStringLegacyNullToEmptyStringOrTrustedHTML* outerHTML() const;
   void setInnerHTML(const V8UnionStringLegacyNullToEmptyStringOrTrustedHTML*,
@@ -1435,10 +1424,14 @@
   void setHTMLUnsafe(const V8UnionStringOrTrustedHTML* html,
                      SetHTMLUnsafeOptions*,
                      ExceptionState&);
+  void setHTMLUnsafe(const V8UnionStringOrTrustedHTML* html,
+                     TrustedParserOptions*,
+                     ExceptionState&);
   void setHTML(const String& html, SetHTMLOptions*, ExceptionState&);
+  void setHTML(const String& html, TrustedParserOptions*, ExceptionState&);
 
-  void setPointerCapture(PointerId poinetr_id, ExceptionState&);
-  void releasePointerCapture(PointerId pointer_id, ExceptionState&);
+  void setPointerCapture(PointerId, ExceptionState&);
+  void releasePointerCapture(PointerId, ExceptionState&);
 
   // Returns true iff the element would capture the next pointer event. This
   // is true between a setPointerCapture call and a releasePointerCapture (or
@@ -1913,14 +1906,6 @@
   void SetScrollTargetGroupContainerData(ScrollMarkerGroupData*);
   ScrollMarkerGroupData* GetScrollTargetGroupContainerData() const;
 
-  // Retrieves the element pointed to by this element's 'anchor' content
-  // attribute, if that element exists.
-  // TODO(crbug.com/40059176) If the HTMLAnchorAttribute feature is disabled,
-  // this will return nullptr;
-  Element* anchorElement() const;
-  Element* anchorElementForBinding() const;
-  void setAnchorElementForBinding(Element*);
-
   AnchorPositionScrollData& EnsureAnchorPositionScrollData();
   void RemoveAnchorPositionScrollData();
   AnchorPositionScrollData* GetAnchorPositionScrollData() const;
@@ -1936,10 +1921,6 @@
   bool MayBeImplicitAnchor() const;
   void SetMayBeImplicitAnchor();
 
-  bool HasAnchorElementObserverForTesting() const {
-    return GetAnchorElementObserver();
-  }
-
   // https://drafts.csswg.org/css-anchor-1/#implicit-anchor-element
   Element* ImplicitAnchorElement() const;
 
@@ -2214,9 +2195,6 @@
 
   void NotifyAXOfAttachedSubtree();
 
-  AnchorElementObserver& EnsureAnchorElementObserver();
-  AnchorElementObserver* GetAnchorElementObserver() const;
-
   // If the only inherited changes in the parent element are independent,
   // these changes can be directly propagated to this element (the child).
   // If these conditions are met, propagates the changes to the current style
@@ -2543,17 +2521,26 @@
                                                         const QualifiedName&,
                                                         const AtomicString&);
 
-  void SetInnerHTMLInternal(
-      const String&,
-      ParseDeclarativeShadowRoots parse_declarative_shadows,
-      ForceHtml force_html_over_xml,
-      // When called from SetHTML or SetHTMLUnsafe, SetInnerHTMLInternal must
-      // process their options dictionary, which you can pass into |options|.
-      // When called from a method without options, like the classic innerHTML
-      // setter, you can pass std::monostate{} to designate no options.
-      std::variant<std::monostate, SetHTMLOptions*, SetHTMLUnsafeOptions*>
-          options,
-      ExceptionState&);
+  void SetInnerHTMLInternal(const String&,
+                            FragmentParserConfig::ParseDeclarativeShadowRoots,
+                            FragmentParserConfig::ForceHtml,
+                            Sanitizer::Mode,
+                            const FragmentParserOptions&,
+                            const AtomicString& property_name,
+                            ExceptionState&);
+
+  template <typename T>
+  String CheckTrustedTypes(T* html,
+                           const AtomicString& property_name,
+                           ExceptionState& exception_state) const {
+    return TrustedTypesCheckForHTML(html, GetExecutionContext(),
+                                    trusted_types_names::kElement,
+                                    property_name, exception_state);
+  }
+
+  void InsertAdjacentHTMLInternal(const String& where,
+                                  const String& input,
+                                  ExceptionState& exception_state);
 
   void RemoveAttrNodeList();
   void DetachAllAttrNodesFromElement();
diff --git a/third_party/blink/renderer/core/dom/element.idl b/third_party/blink/renderer/core/dom/element.idl
index fe228d6..5bfb87e39 100644
--- a/third_party/blink/renderer/core/dom/element.idl
+++ b/third_party/blink/renderer/core/dom/element.idl
@@ -113,17 +113,27 @@
     // https://github.com/whatwg/html/pull/9538
     [RaisesException,MeasureAs=SetHTMLUnsafe,CEReactions] void setHTMLUnsafe((TrustedHTML or DOMString) html);
     // https://wicg.github.io/sanitizer-api/#sanitizer-api
-    // TODO(vogelheim): Merge the two setHTMLUnsafe variants into one, once the
+    // TODO(vogelheim): Merge the 3 setHTMLUnsafe variants into one, once the
     //   different RuntimeEnabled flags are both perma-enabled.
     [RuntimeEnabled=SanitizerAPI,RaisesException,MeasureAs=SetHTMLUnsafe,CEReactions] void setHTMLUnsafe((TrustedHTML or DOMString) html, SetHTMLUnsafeOptions options);
+    [RuntimeEnabled=TrustedTypesCreateParserOptions,RaisesException,MeasureAs=SetHTMLUnsafe,CEReactions] void setHTMLUnsafe((TrustedHTML or DOMString) html, TrustedParserOptions options);
     [RuntimeEnabled=SanitizerAPI,RaisesException,MeasureAs=SetHTMLSafe,CEReactions] void setHTML(DOMString html, optional SetHTMLOptions options = {});
+    [RuntimeEnabled=TrustedTypesCreateParserOptions,RaisesException,MeasureAs=SetHTMLSafe,CEReactions] void setHTML(DOMString html, TrustedParserOptions options);
 
     // https://github.com/whatwg/html/issues/2142
     // https://github.com/whatwg/html/issues/11542
     [RuntimeEnabled=DocumentPatching, CallWith=ScriptState, RaisesException] WritableStream streamAppendHTMLUnsafe(optional (SetHTMLUnsafeOptions or TrustedParserOptions) options = {});
     [RuntimeEnabled=DocumentPatching, CallWith=ScriptState, RaisesException] WritableStream streamHTMLUnsafe(optional (SetHTMLUnsafeOptions or TrustedParserOptions) options = {});
+    [RuntimeEnabled=DocumentPatching, CallWith=ScriptState, RaisesException] WritableStream streamAppendHTML(optional (SetHTMLOptions or TrustedParserOptions) options = {});
+    [RuntimeEnabled=DocumentPatching, CallWith=ScriptState, RaisesException] WritableStream streamHTML(optional (SetHTMLOptions or TrustedParserOptions) options = {});
     [SameObject, PutForwards=value, RuntimeEnabled=DocumentPatching] readonly attribute DOMTokenList marker;
 
+    // https://github.com/whatwg/html/issues/11669
+    [RuntimeEnabled=DocumentPatching, RaisesException] void appendHTML(DOMString html, optional (SetHTMLOptions or TrustedParserOptions) options = {});
+    [RuntimeEnabled=DocumentPatching, RaisesException] void appendHTMLUnsafe((TrustedHTML or DOMString) html, optional (SetHTMLUnsafeOptions or TrustedParserOptions) options = {});
+    [RuntimeEnabled=DocumentPatching, RaisesException] void prependHTML(DOMString html, optional (SetHTMLOptions or TrustedParserOptions) options = {});
+    [RuntimeEnabled=DocumentPatching, RaisesException] void prependHTMLUnsafe((TrustedHTML or DOMString) html, optional (SetHTMLUnsafeOptions or TrustedParserOptions) options = {});
+
     // Declarative Shadow DOM getHTML() function.
     [Affects=Nothing, MeasureAs=ElementGetHTML, RaisesException] DOMString getHTML(optional GetHTMLOptions options = {});
 
@@ -157,9 +167,6 @@
     readonly attribute long clientHeight;
     [RuntimeEnabled=StandardizedBrowserZoom] readonly attribute double currentCSSZoom;
 
-    // Used by both Anchor Positioning and Popover
-    [CEReactions,RuntimeEnabled=HTMLAnchorAttribute,ImplementedAs=anchorElementForBinding] attribute Element? anchorElement;
-
     // Non-standard API
     [MeasureAs=ElementScrollIntoViewIfNeeded] void scrollIntoViewIfNeeded(optional boolean centerIfNeeded);
 
diff --git a/third_party/blink/renderer/core/dom/element_rare_data_vector.cc b/third_party/blink/renderer/core/dom/element_rare_data_vector.cc
index 9f17fc439..dfeaf59 100644
--- a/third_party/blink/renderer/core/dom/element_rare_data_vector.cc
+++ b/third_party/blink/renderer/core/dom/element_rare_data_vector.cc
@@ -33,7 +33,6 @@
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
 #include "third_party/blink/renderer/core/dom/space_split_string.h"
 #include "third_party/blink/renderer/core/editing/ime/edit_context.h"
-#include "third_party/blink/renderer/core/html/anchor_element_observer.h"
 #include "third_party/blink/renderer/core/html/custom/custom_element_definition.h"
 #include "third_party/blink/renderer/core/html/custom/custom_element_registry.h"
 #include "third_party/blink/renderer/core/html/custom/element_internals.h"
@@ -652,21 +651,6 @@
       FieldId::kExplicitlySetElementsForAttr);
 }
 
-std::pair<std::reference_wrapper<AnchorElementObserver>, ElementRareDataVector*>
-ElementRareDataVector::EnsureAnchorElementObserver(
-    Element* new_source_element) {
-  DCHECK(!GetAnchorElementObserver() ||
-         GetAnchorElementObserver()->GetSourceElement() == new_source_element);
-  CHECK(RuntimeEnabledFeatures::HTMLAnchorAttributeEnabled());
-  return EnsureField<AnchorElementObserver>(FieldId::kAnchorElementObserver,
-                                            new_source_element);
-}
-
-AnchorElementObserver* ElementRareDataVector::GetAnchorElementObserver() const {
-  return static_cast<AnchorElementObserver*>(
-      GetField(FieldId::kAnchorElementObserver));
-}
-
 bool ElementRareDataVector::HasCustomElementRegistrySet() const {
   DCHECK(RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled());
   return flags_.has_custom_element_registry_;
diff --git a/third_party/blink/renderer/core/dom/element_rare_data_vector.h b/third_party/blink/renderer/core/dom/element_rare_data_vector.h
index aec4ba35..c9ff424 100644
--- a/third_party/blink/renderer/core/dom/element_rare_data_vector.h
+++ b/third_party/blink/renderer/core/dom/element_rare_data_vector.h
@@ -36,7 +36,6 @@
 class ElementIntersectionObserverData;
 class ContainerQueryEvaluator;
 class EditContext;
-class AnchorElementObserver;
 class InlineStylePropertyMap;
 class ElementInternals;
 class DisplayLockContext;
@@ -400,11 +399,6 @@
             ElementRareDataVector*>
   EnsureAnchorPositionScrollData(Element*);
 
-  std::pair<std::reference_wrapper<AnchorElementObserver>,
-            ElementRareDataVector*>
-  EnsureAnchorElementObserver(Element*);
-  AnchorElementObserver* GetAnchorElementObserver() const;
-
   bool HasCustomElementRegistrySet() const;
   CustomElementRegistry* GetCustomElementRegistry() const;
   [[nodiscard]] ElementRareDataVector* SetCustomElementRegistry(
@@ -605,34 +599,33 @@
     kIsValue = 21,
     kSavedLayerScrollOffset = 22,
     kAnchorPositionScrollData = 23,
-    kAnchorElementObserver = 24,
-    kMayBeImplicitAnchor = 25,
-    kLastRememberedBlockSize = 26,
-    kLastRememberedInlineSize = 27,
-    kRestrictionTargetId = 28,
-    kStyleScopeData = 29,
-    kOutOfFlowData = 30,
-    kInvokerData = 31,
-    kInterestInvokerTargetData = 32,
-    kScrollMarkerGroupData = 33,
-    kScrollMarkerGroupContainerData = 34,
-    kExplicitlySetElementsForAttr = 35,
-    kCSSPseudoElementData = 36,
-    kCustomElementRegistry = 37,
-    kAnimationTriggerData = 38,
-    kFocusgroupLastFocused = 39,
-    kDisplayAdElementMonitor = 40,
-    kOverscrollAreaTracker = 41,
-    kAltContentData = 42,
-    kOverscrollContainer = 43,
-    kTrackedElementRect = 44,
-    kNodeLists = 45,
-    kMutationObserverData = 46,
-    kFlatTreeNodeData = 47,
-    kScrollTimelines = 48,
-    kDOMNodeId = 50,
-    kMarker = 51,
-    kNumFields = 52,
+    kMayBeImplicitAnchor = 24,
+    kLastRememberedBlockSize = 25,
+    kLastRememberedInlineSize = 26,
+    kRestrictionTargetId = 27,
+    kStyleScopeData = 28,
+    kOutOfFlowData = 29,
+    kInvokerData = 30,
+    kInterestInvokerTargetData = 31,
+    kScrollMarkerGroupData = 32,
+    kScrollMarkerGroupContainerData = 33,
+    kExplicitlySetElementsForAttr = 34,
+    kCSSPseudoElementData = 35,
+    kCustomElementRegistry = 36,
+    kAnimationTriggerData = 37,
+    kFocusgroupLastFocused = 38,
+    kDisplayAdElementMonitor = 39,
+    kOverscrollAreaTracker = 40,
+    kAltContentData = 41,
+    kOverscrollContainer = 42,
+    kTrackedElementRect = 43,
+    kNodeLists = 44,
+    kMutationObserverData = 45,
+    kFlatTreeNodeData = 46,
+    kScrollTimelines = 47,
+    kDOMNodeId = 49,
+    kMarker = 50,
+    kNumFields = 51,
   };
 
   inline const Member<ElementRareDataField>* ArrayBase() const {
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
index 87d86f4a..896f25a8 100644
--- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
+++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -247,7 +247,13 @@
   // activationTarget to parent.
   if (is_activation_event && !activation_target && event_->bubbles()) {
     wtf_size_t size = event_->GetEventPath().size();
-    for (wtf_size_t i = 1; i < size; ++i) {
+    // When node_ is a pseudo-element, CalculatePath() replaces it with its
+    // UltimateOriginatingElement() at path index 0 (pseudos are not exposed
+    // in the event path). That means path[0] is the originating element, not
+    // node_ itself, so we must start the search at i=0 to avoid skipping the
+    // originating element (e.g., <summary> whose ::marker was clicked).
+    const wtf_size_t start = node_->IsPseudoElement() ? 0 : 1;
+    for (wtf_size_t i = start; i < size; ++i) {
       Node& target = event_->GetEventPath()[i].GetNode();
       if (target.HasActivationBehavior()) {
         activation_target = &target;
@@ -453,7 +459,12 @@
     if (!event_->DefaultHandled() && !event_->defaultPrevented() &&
         event_->bubbles()) {
       wtf_size_t size = event_->GetEventPath().size();
-      for (wtf_size_t i = 1; i < size; ++i) {
+      // When node_ is a pseudo-element, CalculatePath() replaces it at path
+      // index 0 with its UltimateOriginatingElement() (pseudos are not exposed
+      // in the event path). Start at i=0 so the originating element's
+      // DefaultEventHandler is also invoked (e.g., <summary> for ::marker).
+      const wtf_size_t start = node_->IsPseudoElement() ? 0 : 1;
+      for (wtf_size_t i = start; i < size; ++i) {
         event_->GetEventPath()[i].GetNode().DefaultEventHandler(*event_);
         if (event_->DefaultHandled() || event_->defaultPrevented()) {
           break;
diff --git a/third_party/blink/renderer/core/dom/events/event_path.cc b/third_party/blink/renderer/core/dom/events/event_path.cc
index 0bc3153..e285f36 100644
--- a/third_party/blink/renderer/core/dom/events/event_path.cc
+++ b/third_party/blink/renderer/core/dom/events/event_path.cc
@@ -40,11 +40,18 @@
 namespace blink {
 
 EventTarget& EventPath::EventTargetRespectingTargetRules(Node& reference_node) {
-  if (reference_node.IsPseudoElement() &&
-      !reference_node.IsScrollControlPseudoElement() &&
-      !reference_node.IsInterestHintPseudoElement()) {
-    DCHECK(reference_node.parentNode());
-    return *reference_node.parentNode();
+  if (auto* pseudo = DynamicTo<PseudoElement>(reference_node)) {
+    // Pseudos with activation behavior (::scroll-marker, ::scroll-button,
+    // ::interest-hint) are kept as event.RawTarget() so their
+    // DefaultEventHandler fires correctly (the handler checks
+    // |event.RawTarget() == this|).
+    // Other pseudos resolve to their originating element.
+    if (!pseudo->HasActivationBehavior()) {
+      if (pseudo->isConnected()) {
+        return pseudo->UltimateOriginatingElement();
+      }
+      // Disconnected pseudo — fall back to the pseudo itself.
+    }
   }
 
   return reference_node;
diff --git a/third_party/blink/renderer/core/dom/interest_hint_pseudo_element.h b/third_party/blink/renderer/core/dom/interest_hint_pseudo_element.h
index a30919f..974902d 100644
--- a/third_party/blink/renderer/core/dom/interest_hint_pseudo_element.h
+++ b/third_party/blink/renderer/core/dom/interest_hint_pseudo_element.h
@@ -19,7 +19,6 @@
   void DefaultEventHandler(Event&) override;
   bool HasActivationBehavior() const final { return true; }
   bool WillRespondToMouseClickEvents() override { return true; }
-  Node* InnerNodeForHitTesting() final { return this; }
 
   FocusableState SupportsFocus(UpdateBehavior update_behavior) const final;
 
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc
index 4c55821..85c9a3e3 100644
--- a/third_party/blink/renderer/core/dom/node.cc
+++ b/third_party/blink/renderer/core/dom/node.cc
@@ -79,6 +79,7 @@
 #include "third_party/blink/renderer/core/dom/user_action_element_set.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
+#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
 #include "third_party/blink/renderer/core/event_target_names.h"
 #include "third_party/blink/renderer/core/events/event_util.h"
 #include "third_party/blink/renderer/core/events/gesture_event.h"
@@ -111,6 +112,7 @@
 #include "third_party/blink/renderer/core/html/html_object_element.h"
 #include "third_party/blink/renderer/core/html/html_script_element.h"
 #include "third_party/blink/renderer/core/html/html_slot_element.h"
+#include "third_party/blink/renderer/core/html/parser/fragment_parser_options.h"
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/input/event_handler.h"
 #include "third_party/blink/renderer/core/input/input_device_capabilities.h"
@@ -131,6 +133,8 @@
 #include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
 #include "third_party/blink/renderer/core/svg/svg_element.h"
 #include "third_party/blink/renderer/core/trustedtypes/trusted_script.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_types_names.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
 #include "third_party/blink/renderer/core/view_transition/view_transition_pseudo_element_base.h"
 #include "third_party/blink/renderer/core/view_transition/view_transition_supplement.h"
 #include "third_party/blink/renderer/core/view_transition/view_transition_utils.h"
@@ -1226,6 +1230,110 @@
   parent->InsertBefore(node_vector, viable_next_sibling, exception_state);
 }
 
+namespace {
+bool CanInsertHTMLToParent(Node* child) {
+  const ContainerNode* parent = child->parentNode();
+  return parent && (parent->IsElementNode() || parent->IsShadowRoot());
+}
+}  // namespace
+
+void Node::replaceWithHTML(const String& html,
+                           V8UnionSetHTMLOptionsOrTrustedParserOptions* options,
+                           ExceptionState& exception_state) {
+  if (CanInsertHTMLToParent(this)) {
+    parentNode()->ReplaceChildWithHTML(
+        this, html,
+        blink::GetFragmentParserConfig(
+            Sanitizer::Mode::kSafe, trusted_types_names::kNode,
+            trusted_types_names::kReplaceWithHTML, parentNode()),
+        FragmentParserOptions::From(options), exception_state);
+  }
+}
+
+void Node::replaceWithHTMLUnsafe(
+    const V8UnionStringOrTrustedHTML* html,
+    V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions* options,
+    ExceptionState& exception_state) {
+  if (!CanInsertHTMLToParent(this)) {
+    return;
+  }
+  const FragmentParserConfig config = blink::GetFragmentParserConfig(
+      Sanitizer::Mode::kUnsafe, trusted_types_names::kNode,
+      trusted_types_names::kReplaceWithHTMLUnsafe, parentNode());
+
+  parentNode()->ReplaceChildWithHTML(
+      this,
+      TrustedTypesCheckForHTML(html, GetExecutionContext(),
+                               config.interface_name, config.property_name,
+                               exception_state),
+      config, FragmentParserOptions::From(options), exception_state);
+}
+
+void Node::beforeHTML(const String& html,
+                      V8UnionSetHTMLOptionsOrTrustedParserOptions* options,
+                      ExceptionState& exception_state) {
+  if (CanInsertHTMLToParent(this)) {
+    parentNode()->InsertHTMLBefore(
+        this, html,
+        blink::GetFragmentParserConfig(
+            Sanitizer::Mode::kSafe, trusted_types_names::kNode,
+            trusted_types_names::kBeforeHTML, parentNode()),
+
+        FragmentParserOptions::From(options), exception_state);
+  }
+}
+
+void Node::beforeHTMLUnsafe(
+    const V8UnionStringOrTrustedHTML* html,
+    V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions* options,
+    ExceptionState& exception_state) {
+  if (!CanInsertHTMLToParent(this)) {
+    return;
+  }
+  const FragmentParserConfig config = blink::GetFragmentParserConfig(
+      Sanitizer::Mode::kUnsafe, trusted_types_names::kNode,
+      trusted_types_names::kBeforeHTMLUnsafe, parentNode());
+
+  parentNode()->InsertHTMLBefore(
+      this,
+      TrustedTypesCheckForHTML(html, GetExecutionContext(),
+                               config.interface_name, config.property_name,
+                               exception_state),
+      config, FragmentParserOptions::From(options), exception_state);
+}
+
+void Node::afterHTML(const String& html,
+                     V8UnionSetHTMLOptionsOrTrustedParserOptions* options,
+                     ExceptionState& exception_state) {
+  if (CanInsertHTMLToParent(this)) {
+    parentNode()->InsertHTMLBefore(
+        nextSibling(), html,
+        blink::GetFragmentParserConfig(
+            Sanitizer::Mode::kSafe, trusted_types_names::kNode,
+            trusted_types_names::kAfterHTML, parentNode()),
+        FragmentParserOptions::From(options), exception_state);
+  }
+}
+
+void Node::afterHTMLUnsafe(
+    const V8UnionStringOrTrustedHTML* html,
+    V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions* options,
+    ExceptionState& exception_state) {
+  if (!CanInsertHTMLToParent(this)) {
+    return;
+  }
+  const FragmentParserConfig config = blink::GetFragmentParserConfig(
+      Sanitizer::Mode::kUnsafe, trusted_types_names::kNode,
+      trusted_types_names::kAfterHTMLUnsafe, parentNode());
+
+  parentNode()->InsertHTMLBefore(
+      nextSibling(),
+      TrustedTypesCheckForHTML(html, GetExecutionContext(),
+                               config.interface_name, config.property_name,
+                               exception_state),
+      config, FragmentParserOptions::From(options), exception_state);
+}
+
 void Node::replaceWith(
     const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes,
     ExceptionState& exception_state) {
diff --git a/third_party/blink/renderer/core/dom/node.h b/third_party/blink/renderer/core/dom/node.h
index 17c6ea7..a3a28db9f 100644
--- a/third_party/blink/renderer/core/dom/node.h
+++ b/third_party/blink/renderer/core/dom/node.h
@@ -97,7 +97,10 @@
 class StyleChangeReasonForTracing;
 class TextVisitor;
 class V8UnionNodeOrStringOrTrustedScript;
+class V8UnionStringOrTrustedHTML;
 class V8UnionStringOrTrustedScript;
+class V8UnionSetHTMLOptionsOrTrustedParserOptions;
+class V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions;
 class WebPluginContainerImpl;
 
 struct PhysicalRect;
@@ -268,6 +271,24 @@
   void remove(ExceptionState&);
   void remove();
 
+  void beforeHTML(const String& html,
+                  V8UnionSetHTMLOptionsOrTrustedParserOptions* options,
+                  ExceptionState&);
+  void beforeHTMLUnsafe(const V8UnionStringOrTrustedHTML* html,
+                        V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions*,
+                        ExceptionState&);
+  void afterHTML(const String& html,
+                 V8UnionSetHTMLOptionsOrTrustedParserOptions* options,
+                 ExceptionState&);
+  void afterHTMLUnsafe(const V8UnionStringOrTrustedHTML* html,
+                       V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions*,
+                       ExceptionState&);
+  void replaceWithHTML(const String& html,
+                       V8UnionSetHTMLOptionsOrTrustedParserOptions* options,
+                       ExceptionState&);
+  void replaceWithHTMLUnsafe(const V8UnionStringOrTrustedHTML* html,
+                             V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions*,
+                             ExceptionState&);
   // NonDocumentTypeChildNode interface. These functions are only actually
   // web-exposed on  interfaces that include NonDocumentTypeChildNode in their
   // idl.
diff --git a/third_party/blink/renderer/core/dom/pseudo_element.cc b/third_party/blink/renderer/core/dom/pseudo_element.cc
index d174cc5..97ddcd1 100644
--- a/third_party/blink/renderer/core/dom/pseudo_element.cc
+++ b/third_party/blink/renderer/core/dom/pseudo_element.cc
@@ -694,6 +694,32 @@
   return parent;
 }
 
+// static
+bool PseudoElement::SupportsHitTesting(PseudoId pseudo_id) {
+  // Returns true for pseudo-elements that should participate in hit testing.
+  // This gates whether the pseudo appears via InnerPossiblyPseudoElement().
+  // Event targeting (which pseudo keeps event.RawTarget vs resolves to
+  // originating) is determined by HasActivationBehavior() in
+  // EventTargetRespectingTargetRules.
+  switch (pseudo_id) {
+    case kPseudoIdInterestHint:
+    case kPseudoIdScrollMarker:
+    case kPseudoIdScrollMarkerGroupBefore:
+    case kPseudoIdScrollMarkerGroupAfter:
+    case kPseudoIdScrollButtonBlockStart:
+    case kPseudoIdScrollButtonInlineStart:
+    case kPseudoIdScrollButtonInlineEnd:
+    case kPseudoIdScrollButtonBlockEnd:
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool PseudoElement::SupportsHitTesting() const {
+  return SupportsHitTesting(pseudo_id_);
+}
+
 void PseudoElement::AccessKeyAction(
     SimulatedClickCreationScope creation_scope) {
   // If this is a pseudo-element with activation behavior such as a
diff --git a/third_party/blink/renderer/core/dom/pseudo_element.h b/third_party/blink/renderer/core/dom/pseudo_element.h
index 499fbc28..4c77913 100644
--- a/third_party/blink/renderer/core/dom/pseudo_element.h
+++ b/third_party/blink/renderer/core/dom/pseudo_element.h
@@ -83,10 +83,23 @@
   static AtomicString PseudoElementNameForEvents(Element*);
   static bool IsWebExposed(PseudoId, const Node*);
 
-  // Pseudo-elements are not allowed to be the inner node for hit testing.
-  // Find the closest ancestor which is a real dom node.
+  // Returns the node to store as |inner_node_| in HitTestResult.
+  //
+  // Always resolves to the originating DOM element, for every pseudo-element
+  // including those with activation behavior (::scroll-marker, ::scroll-button,
+  // ::interest-hint). This enforces the invariant that |inner_node_| is always
+  // a real (non-pseudo) Element, which is required for:
+  //   - SelectionController: IsEditable / CanStartSelection / GetPosition
+  //
+  // Dispatch targets the pseudo via InnerPossiblyPseudoElement() instead:
+  //   - DispatchMousePointerEvent uses InnerPossiblyPseudoElement() so
+  //     EventDispatcher::node_ = the pseudo, keeping HasActivationBehavior()
+  //     checks, DefaultEventHandler dispatch, and event.pseudoTarget working.
   virtual Node* InnerNodeForHitTesting();
 
+  bool SupportsHitTesting() const;
+  static bool SupportsHitTesting(PseudoId pseudo_id);
+
   void AccessKeyAction(SimulatedClickCreationScope creation_scope) override;
 
   // Returns the DOM element that this pseudo-element originates from. If the
diff --git a/third_party/blink/renderer/core/dom/range.cc b/third_party/blink/renderer/core/dom/range.cc
index a9e08db..0b1feb3 100644
--- a/third_party/blink/renderer/core/dom/range.cc
+++ b/third_party/blink/renderer/core/dom/range.cc
@@ -55,11 +55,13 @@
 #include "third_party/blink/renderer/core/html/html_body_element.h"
 #include "third_party/blink/renderer/core/html/html_element.h"
 #include "third_party/blink/renderer/core/html/html_html_element.h"
+#include "third_party/blink/renderer/core/html/parser/fragment_parser_options.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/layout/layout_text.h"
 #include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
 #include "third_party/blink/renderer/core/page/scrolling/sync_scroll_attempt_heuristic.h"
 #include "third_party/blink/renderer/core/svg/svg_svg_element.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_types_names.h"
 #include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -999,9 +1001,10 @@
 
   // Step 1: Invoke Get Trusted Type compliant string.
   String compliant_markup = TrustedTypesCheckForHTML(
-      markup, OwnerDocument().GetExecutionContext(),
+      markup, owner_document_->GetExecutionContext(),
       trusted_types_names::kRange,
       trusted_types_names::kCreateContextualFragment, exception_state);
+
   if (exception_state.HadException()) {
     return nullptr;
   }
@@ -1039,9 +1042,8 @@
   }
 
   // Steps 7, 8, 9: Invoke fragment parsing, etc.
-  return blink::CreateContextualFragment(
-      compliant_markup, element,
-      kAllowScriptingContentAndDoNotMarkAlreadyStarted, exception_state);
+  return blink::CreateContextualFragment(compliant_markup, element,
+                                         exception_state);
 }
 
 void Range::detach() {
diff --git a/third_party/blink/renderer/core/dom/scroll_button_pseudo_element.h b/third_party/blink/renderer/core/dom/scroll_button_pseudo_element.h
index cb5ab1c..fa2028ef 100644
--- a/third_party/blink/renderer/core/dom/scroll_button_pseudo_element.h
+++ b/third_party/blink/renderer/core/dom/scroll_button_pseudo_element.h
@@ -21,7 +21,6 @@
   void DefaultEventHandler(Event&) override;
   bool HasActivationBehavior() const final { return true; }
   bool WillRespondToMouseClickEvents() override { return true; }
-  Node* InnerNodeForHitTesting() final { return this; }
 
   bool IsEnabled() const { return enabled_; }
   bool IsDisabledFormControl() const final { return !IsEnabled(); }
diff --git a/third_party/blink/renderer/core/dom/scroll_marker_group_pseudo_element.h b/third_party/blink/renderer/core/dom/scroll_marker_group_pseudo_element.h
index 19382ce..33d0f114 100644
--- a/third_party/blink/renderer/core/dom/scroll_marker_group_pseudo_element.h
+++ b/third_party/blink/renderer/core/dom/scroll_marker_group_pseudo_element.h
@@ -56,8 +56,6 @@
 
   void ScrollSelectedIntoView(bool apply_snap_alignment);
 
-  Node* InnerNodeForHitTesting() final { return this; }
-
   // Returns the mode of scroll-marker-group property of the originating
   // element.
   CORE_EXPORT ScrollMarkerGroup::ScrollMarkerMode ScrollMarkerGroupMode() const;
diff --git a/third_party/blink/renderer/core/dom/scroll_marker_pseudo_element.h b/third_party/blink/renderer/core/dom/scroll_marker_pseudo_element.h
index 78da9ea..95c6647 100644
--- a/third_party/blink/renderer/core/dom/scroll_marker_pseudo_element.h
+++ b/third_party/blink/renderer/core/dom/scroll_marker_pseudo_element.h
@@ -23,7 +23,6 @@
   void DefaultEventHandler(Event&) override;
   bool HasActivationBehavior() const final { return true; }
   bool WillRespondToMouseClickEvents() override { return true; }
-  Node* InnerNodeForHitTesting() final { return this; }
   void SetScrollMarkerGroup(
       ScrollMarkerGroupPseudoElement* scroll_marker_group);
   ScrollMarkerGroupPseudoElement* ScrollMarkerGroup() const {
diff --git a/third_party/blink/renderer/core/dom/shadow_root.cc b/third_party/blink/renderer/core/dom/shadow_root.cc
index 7455045e..b1c450cb 100644
--- a/third_party/blink/renderer/core/dom/shadow_root.cc
+++ b/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -39,6 +39,7 @@
 #include "third_party/blink/renderer/core/css/style_change_reason.h"
 #include "third_party/blink/renderer/core/css/style_engine.h"
 #include "third_party/blink/renderer/core/css/style_sheet_list.h"
+#include "third_party/blink/renderer/core/dom/document_fragment.h"
 #include "third_party/blink/renderer/core/dom/element_traversal.h"
 #include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
 #include "third_party/blink/renderer/core/dom/id_target_observer.h"
@@ -55,12 +56,15 @@
 #include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/core/html/custom/custom_element_registry.h"
 #include "third_party/blink/renderer/core/html/html_slot_element.h"
+#include "third_party/blink/renderer/core/html/parser/fragment_parser_options.h"
 #include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
 #include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h"
 #include "third_party/blink/renderer/core/sanitizer/sanitizer_api.h"
 #include "third_party/blink/renderer/core/script/modulator.h"
 #include "third_party/blink/renderer/core/script/module_script.h"
 #include "third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_parser_options.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_types_names.h"
 #include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -158,71 +162,77 @@
 void ShadowRoot::SetInnerHTMLWithoutTrustedTypes(
     const String& html,
     ExceptionState& exception_state) {
-  if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML(
-          html, &host(), kAllowScriptingContent,
-          Element::ParseDeclarativeShadowRoots::kDontParse,
-          Element::ForceHtml::kDontForce, ForceInertTemplate::kDontForce,
-          customElementRegistry(), exception_state)) {
-    ReplaceChildrenWithFragment(this, fragment, exception_state);
-  }
+  SetInnerHTMLInternal(
+      html, FragmentParserOptions(), Sanitizer::Mode::kUnsafe,
+      FragmentParserConfig::ParseDeclarativeShadowRoots::kDontParse,
+      trusted_types_names::kInnerHTML, exception_state);
 }
 
 void ShadowRoot::setInnerHTML(
     const V8UnionStringLegacyNullToEmptyStringOrTrustedHTML* html,
     ExceptionState& exception_state) {
-  String compliant_html = TrustedTypesCheckForHTML(
-      html, GetExecutionContext(), trusted_types_names::kShadowRoot,
+  SetInnerHTMLInternal(
+      CheckHTML(html, trusted_types_names::kInnerHTML, exception_state),
+      FragmentParserOptions(), Sanitizer::Mode::kUnsafe,
+      FragmentParserConfig::ParseDeclarativeShadowRoots::kDontParse,
       trusted_types_names::kInnerHTML, exception_state);
-  if (exception_state.HadException()) {
-    return;
-  }
-  SetInnerHTMLWithoutTrustedTypes(compliant_html, exception_state);
 }
 
 void ShadowRoot::setHTMLUnsafe(const V8UnionStringOrTrustedHTML* html,
                                ExceptionState& exception_state) {
   UseCounter::Count(GetDocument(), WebFeature::kHTMLUnsafeMethods);
-  String compliant_html = TrustedTypesCheckForHTML(
-      html, GetExecutionContext(), trusted_types_names::kShadowRoot,
+  SetInnerHTMLInternal(
+      CheckHTML(html, trusted_types_names::kSetHTMLUnsafe, exception_state),
+      FragmentParserOptions(), Sanitizer::Mode::kUnsafe,
+      FragmentParserConfig::ParseDeclarativeShadowRoots::kParse,
       trusted_types_names::kSetHTMLUnsafe, exception_state);
-  if (exception_state.HadException()) {
-    return;
-  }
-  if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML(
-          compliant_html, &host(), kAllowScriptingContent,
-          Element::ParseDeclarativeShadowRoots::kParse,
-          Element::ForceHtml::kDontForce, ForceInertTemplate::kForce,
-          customElementRegistry(), exception_state)) {
-    if (RuntimeEnabledFeatures::SanitizerAPIEnabled()) {
-      SanitizerAPI::SanitizeUnsafeInternal(this, fragment, nullptr,
-                                           exception_state);
-    }
-    ReplaceChildrenWithFragment(this, fragment, exception_state);
-  }
 }
 
+// TODO(nrosenthal): merge these calls once all the flags are merged.
 void ShadowRoot::setHTMLUnsafe(const V8UnionStringOrTrustedHTML* html,
                                SetHTMLUnsafeOptions* options,
                                ExceptionState& exception_state) {
-  String compliant_html = TrustedTypesCheckForHTML(
-      html, GetExecutionContext(), trusted_types_names::kShadowRoot,
+  UseCounter::Count(GetDocument(), WebFeature::kHTMLUnsafeMethods);
+  SetInnerHTMLInternal(
+      CheckHTML(html, trusted_types_names::kSetHTMLUnsafe, exception_state),
+      FragmentParserOptions(options), Sanitizer::Mode::kUnsafe,
+      FragmentParserConfig::ParseDeclarativeShadowRoots::kParse,
       trusted_types_names::kSetHTMLUnsafe, exception_state);
+}
+
+void ShadowRoot::setHTMLUnsafe(const V8UnionStringOrTrustedHTML* html,
+                               TrustedParserOptions* options,
+                               ExceptionState& exception_state) {
+  UseCounter::Count(GetDocument(), WebFeature::kHTMLUnsafeMethods);
+  SetInnerHTMLInternal(
+      CheckHTML(html, trusted_types_names::kSetHTMLUnsafe, exception_state),
+      FragmentParserOptions(options), Sanitizer::Mode::kUnsafe,
+      FragmentParserConfig::ParseDeclarativeShadowRoots::kParse,
+      trusted_types_names::kSetHTMLUnsafe, exception_state);
+}
+
+void ShadowRoot::SetInnerHTMLInternal(
+    const String& html,
+    FragmentParserOptions options,
+    Sanitizer::Mode sanitizer_mode,
+    FragmentParserConfig::ParseDeclarativeShadowRoots parse_shadow_roots,
+    const AtomicString& property_name,
+    ExceptionState& exception_state) {
   if (exception_state.HadException()) {
     return;
   }
-  if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML(
-          compliant_html, &host(),
-          RuntimeEnabledFeatures::SetHTMLCanRunScriptsEnabled() &&
-                  options->runScripts()
-              ? kAllowScriptingContentAndDoNotMarkAlreadyStarted
-              : kAllowScriptingContent,
-          Element::ParseDeclarativeShadowRoots::kParse,
-          Element::ForceHtml::kDontForce, ForceInertTemplate::kForce,
-          customElementRegistry(), exception_state)) {
-    if (RuntimeEnabledFeatures::SanitizerAPIEnabled()) {
-      SanitizerAPI::SanitizeUnsafeInternal(this, fragment, options,
-                                           exception_state);
-    }
+
+  if (DocumentFragment* fragment = ParseHTMLFragment(
+          html,
+          {
+              .sanitizer_mode = sanitizer_mode,
+              .parse_declarative_shadows = parse_shadow_roots,
+              .interface_name = trusted_types_names::kShadowRoot,
+              .property_name = property_name,
+              .context_element = &host(),
+              .registry = customElementRegistry(),
+          },
+          options, exception_state)) {
     ReplaceChildrenWithFragment(this, fragment, exception_state);
   }
 }
@@ -230,17 +240,19 @@
 void ShadowRoot::setHTML(const String& html,
                          SetHTMLOptions* options,
                          ExceptionState& exception_state) {
-  if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML(
-          html, &host(), kAllowScriptingContent,
-          Element::ParseDeclarativeShadowRoots::kParse,
-          Element::ForceHtml::kDontForce, ForceInertTemplate::kForce,
-          customElementRegistry(), exception_state)) {
-    if (RuntimeEnabledFeatures::SanitizerAPIEnabled()) {
-      SanitizerAPI::SanitizeSafeInternal(this, fragment, options,
-                                         exception_state);
-    }
-    ReplaceChildrenWithFragment(this, fragment, exception_state);
-  }
+  SetInnerHTMLInternal(
+      html, FragmentParserOptions(options), Sanitizer::Mode::kSafe,
+      FragmentParserConfig::ParseDeclarativeShadowRoots::kParse,
+      trusted_types_names::kSetHTML, exception_state);
+}
+
+void ShadowRoot::setHTML(const String& html,
+                         TrustedParserOptions* options,
+                         ExceptionState& exception_state) {
+  SetInnerHTMLInternal(
+      html, FragmentParserOptions(options), Sanitizer::Mode::kSafe,
+      FragmentParserConfig::ParseDeclarativeShadowRoots::kParse,
+      trusted_types_names::kSetHTML, exception_state);
 }
 
 void ShadowRoot::RebuildLayoutTree(WhitespaceAttacher& whitespace_attacher) {
diff --git a/third_party/blink/renderer/core/dom/shadow_root.h b/third_party/blink/renderer/core/dom/shadow_root.h
index f071b4b..6a270f9 100644
--- a/third_party/blink/renderer/core/dom/shadow_root.h
+++ b/third_party/blink/renderer/core/dom/shadow_root.h
@@ -36,6 +36,8 @@
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/element_rare_data_field.h"
 #include "third_party/blink/renderer/core/dom/tree_scope.h"
+#include "third_party/blink/renderer/core/html/parser/fragment_parser_options.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_parser_options.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -136,7 +138,12 @@
   void setHTMLUnsafe(const V8UnionStringOrTrustedHTML* html,
                      SetHTMLUnsafeOptions*,
                      ExceptionState&);
+  void setHTMLUnsafe(const V8UnionStringOrTrustedHTML* html,
+                     TrustedParserOptions*,
+                     ExceptionState&);
   void setHTML(const String& html, SetHTMLOptions*, ExceptionState&);
+  void setHTML(const String& html, TrustedParserOptions*, ExceptionState&);
+
   const Vector<AtomicString>& marker() const { return markers_; }
 
   Node* Clone(Document& factory,
@@ -223,6 +230,21 @@
   }
 
   void ReferenceTargetChanged();
+  void SetInnerHTMLInternal(const String& html,
+                            FragmentParserOptions,
+                            Sanitizer::Mode,
+                            FragmentParserConfig::ParseDeclarativeShadowRoots,
+                            const AtomicString& property_name,
+                            ExceptionState&);
+
+  template <class T>
+  String CheckHTML(const T* html,
+                   const AtomicString& property_name,
+                   ExceptionState& exception_state) const {
+    return TrustedTypesCheckForHTML(html, GetExecutionContext(),
+                                    trusted_types_names::kShadowRoot,
+                                    property_name, exception_state);
+  }
 
   Member<SlotAssignment> slot_assignment_;
   Vector<AtomicString> markers_;
diff --git a/third_party/blink/renderer/core/dom/shadow_root.idl b/third_party/blink/renderer/core/dom/shadow_root.idl
index 74b00869..e877eac3 100644
--- a/third_party/blink/renderer/core/dom/shadow_root.idl
+++ b/third_party/blink/renderer/core/dom/shadow_root.idl
@@ -56,13 +56,24 @@
     // See https://crbug.com/346835896
     [RuntimeEnabled=ShadowRootReferenceTarget] attribute DOMString? referenceTarget;
 
+    // TODO(nrosenthal): remove duplicates once flags are merged.
     [RaisesException,MeasureAs=SetHTMLUnsafe,CEReactions] void setHTMLUnsafe((TrustedHTML or DOMString) string);
     [RuntimeEnabled=SanitizerAPI,RaisesException,MeasureAs=SetHTMLUnsafe,CEReactions] void setHTMLUnsafe((TrustedHTML or DOMString) html, SetHTMLUnsafeOptions options);
     [RuntimeEnabled=SanitizerAPI,RaisesException,MeasureAs=SetHTMLSafe,CEReactions] void setHTML(DOMString html, optional SetHTMLOptions options = {});
+    [RuntimeEnabled=TrustedTypesCreateParserOptions,RaisesException,MeasureAs=SetHTMLUnsafe,CEReactions] void setHTMLUnsafe((TrustedHTML or DOMString) html, TrustedParserOptions options);
+    [RuntimeEnabled=TrustedTypesCreateParserOptions,RaisesException,MeasureAs=SetHTMLSafe,CEReactions] void setHTML(DOMString html, TrustedParserOptions options);
 
     // https://github.com/whatwg/html/issues/2142
     [RuntimeEnabled=DocumentPatching, CallWith=ScriptState, RaisesException] WritableStream streamAppendHTMLUnsafe(optional (SetHTMLUnsafeOptions or TrustedParserOptions) options = {});
     [RuntimeEnabled=DocumentPatching, CallWith=ScriptState, RaisesException] WritableStream streamHTMLUnsafe(optional (SetHTMLUnsafeOptions or TrustedParserOptions) options = {});
+    [RuntimeEnabled=DocumentPatching, CallWith=ScriptState, RaisesException] WritableStream streamAppendHTML(optional (SetHTMLOptions or TrustedParserOptions) options = {});
+    [RuntimeEnabled=DocumentPatching, CallWith=ScriptState, RaisesException] WritableStream streamHTML(optional (SetHTMLOptions or TrustedParserOptions) options = {});
+
+    // https://github.com/whatwg/html/issues/11669
+    [RuntimeEnabled=DocumentPatching, RaisesException] void appendHTML(DOMString html, optional (SetHTMLOptions or TrustedParserOptions) options = {});
+    [RuntimeEnabled=DocumentPatching, RaisesException] void appendHTMLUnsafe((TrustedHTML or DOMString) html, optional (SetHTMLUnsafeOptions or TrustedParserOptions) options = {});
+    [RuntimeEnabled=DocumentPatching, RaisesException] void prependHTML(DOMString html, optional (SetHTMLOptions or TrustedParserOptions) options = {});
+    [RuntimeEnabled=DocumentPatching, RaisesException] void prependHTMLUnsafe((TrustedHTML or DOMString) html, optional (SetHTMLUnsafeOptions or TrustedParserOptions) options = {});
 };
 
 ShadowRoot includes DocumentOrShadowRoot;
diff --git a/third_party/blink/renderer/core/dom/tree_scope.cc b/third_party/blink/renderer/core/dom/tree_scope.cc
index d3c536bd..7fdc2bc 100644
--- a/third_party/blink/renderer/core/dom/tree_scope.cc
+++ b/third_party/blink/renderer/core/dom/tree_scope.cc
@@ -495,6 +495,8 @@
 void TreeScope::AppendAdoptedStyleSheets(
     HeapVector<Member<CSSStyleSheet>>&& adopted_style_sheets) {
   EnsureAdoptedStyleSheets();
+  adopted_style_sheets_->reserve(adopted_style_sheets_->size() +
+                                 adopted_style_sheets.size());
   for (const auto& sheet : adopted_style_sheets) {
     DCHECK(sheet->IsConstructed());
     DCHECK_EQ(sheet->ConstructorDocument(), GetDocument());
diff --git a/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc b/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc
index 618d475..0ec6166 100644
--- a/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc
+++ b/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc
@@ -24,11 +24,11 @@
 
 // This is a regression test for https://crbug.com/639534
 TEST_F(ApplyBlockElementCommandTest, selectionCrossingOverBody) {
-  GetDocument().head()->InsertAdjacentHTMLWithoutTrustedTypes(
+  GetDocument().head()->InsertAdjacentHTMLWithoutTrustedTypesForTesting(
       "afterbegin",
       "<style> .CLASS13 { -webkit-user-modify: read-write; }</style></head>",
       ASSERT_NO_EXCEPTION);
-  GetDocument().body()->InsertAdjacentHTMLWithoutTrustedTypes(
+  GetDocument().body()->InsertAdjacentHTMLWithoutTrustedTypesForTesting(
       "afterbegin",
       "\n<pre><var id='va' class='CLASS13'>\nC\n</var></pre><input />",
       ASSERT_NO_EXCEPTION);
@@ -63,7 +63,7 @@
 
 // This is a regression test for https://crbug.com/660801
 TEST_F(ApplyBlockElementCommandTest, visibilityChangeDuringCommand) {
-  GetDocument().head()->InsertAdjacentHTMLWithoutTrustedTypes(
+  GetDocument().head()->InsertAdjacentHTMLWithoutTrustedTypesForTesting(
       "afterbegin", "<style>li:first-child { visibility:visible; }</style>",
       ASSERT_NO_EXCEPTION);
   SetBodyContent("<ul style='visibility:hidden'><li>xyz</li></ul>");
diff --git a/third_party/blink/renderer/core/editing/selection_controller.cc b/third_party/blink/renderer/core/editing/selection_controller.cc
index 2e183e4..67fd0c7 100644
--- a/third_party/blink/renderer/core/editing/selection_controller.cc
+++ b/third_party/blink/renderer/core/editing/selection_controller.cc
@@ -36,6 +36,7 @@
 #include "third_party/blink/renderer/core/annotation/annotation_agent_impl.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/pseudo_element.h"
 #include "third_party/blink/renderer/core/editing/bidi_adjustment.h"
 #include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_boundary.h"
@@ -1133,6 +1134,17 @@
   mouse_down_may_start_select_ = (CanMouseDownStartSelect(event.InnerNode()) ||
                                   IsSelectionOverLink(event)) &&
                                  !event.GetScrollbar();
+  // Don't start selection when clicking an activation-behavior pseudo-element
+  // (e.g. ::scroll-marker, ::interest-hint). These act as interactive controls
+  // and clearing the selection on mousedown already happens in
+  // HandleMouseFocus.
+  if (mouse_down_may_start_select_) {
+    if (auto* pseudo = DynamicTo<PseudoElement>(
+            event.GetHitTestResult().InnerPossiblyPseudoNode());
+        pseudo && pseudo->HasActivationBehavior()) {
+      mouse_down_may_start_select_ = false;
+    }
+  }
   mouse_down_was_single_click_on_caret_ = false;
   mouse_down_was_single_click_in_selection_ = false;
   if (!Selection().IsAvailable()) {
diff --git a/third_party/blink/renderer/core/editing/serializers/serialization.cc b/third_party/blink/renderer/core/editing/serializers/serialization.cc
index 777e100..9261c18 100644
--- a/third_party/blink/renderer/core/editing/serializers/serialization.cc
+++ b/third_party/blink/renderer/core/editing/serializers/serialization.cc
@@ -40,6 +40,7 @@
 #include "third_party/blink/public/common/storage_key/storage_key.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/css/counters_attachment_context.h"
 #include "third_party/blink/renderer/core/css/css_identifier_value.h"
 #include "third_party/blink/renderer/core/css/css_property_value_set.h"
 #include "third_party/blink/renderer/core/css/css_value.h"
@@ -49,6 +50,7 @@
 #include "third_party/blink/renderer/core/dom/comment.h"
 #include "third_party/blink/renderer/core/dom/document_fragment.h"
 #include "third_party/blink/renderer/core/dom/document_init.h"
+#include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/element_traversal.h"
 #include "third_party/blink/renderer/core/dom/node_traversal.h"
 #include "third_party/blink/renderer/core/dom/range.h"
@@ -77,6 +79,7 @@
 #include "third_party/blink/renderer/core/html/html_table_cell_element.h"
 #include "third_party/blink/renderer/core/html/html_table_element.h"
 #include "third_party/blink/renderer/core/html/html_template_element.h"
+#include "third_party/blink/renderer/core/html/parser/fragment_parser_options.h"
 #include "third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.h"
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
@@ -84,8 +87,11 @@
 #include "third_party/blink/renderer/core/mathml/mathml_element.h"
 #include "third_party/blink/renderer/core/mathml_names.h"
 #include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/sanitizer/sanitizer_api.h"
 #include "third_party/blink/renderer/core/svg/svg_style_element.h"
 #include "third_party/blink/renderer/core/svg/svg_use_element.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_types_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_context.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -667,12 +673,17 @@
   return fragment;
 }
 
+namespace {
+// ForceInertTemplate specifies whether the HTML parser should parse into an
+// inert (non-active) template document.
+enum class ForceInertTemplate { kDontForce, kForce };
+
 DocumentFragment* CreateFragmentForInnerOuterHTML(
     const String& markup,
     Element* context_element,
     ParserContentPolicy parser_content_policy,
-    Element::ParseDeclarativeShadowRoots parse_declarative_shadows,
-    Element::ForceHtml force_html,
+    FragmentParserConfig::ParseDeclarativeShadowRoots parse_declarative_shadows,
+    FragmentParserConfig::ForceHtml force_html,
     ForceInertTemplate force_inert,
     CustomElementRegistry* registry,
     ExceptionState& exception_state) {
@@ -691,14 +702,15 @@
   DocumentFragment* fragment = DocumentFragment::Create(document);
   document.setAllowDeclarativeShadowRoots(
       parse_declarative_shadows ==
-      Element::ParseDeclarativeShadowRoots::kParse);
+      FragmentParserConfig::ParseDeclarativeShadowRoots::kParse);
 
-  if (IsA<HTMLDocument>(document) || force_html == Element::ForceHtml::kForce) {
+  if (IsA<HTMLDocument>(document) ||
+      force_html == FragmentParserConfig::ForceHtml::kForce) {
     bool log_tag_stats = false;
     base::ElapsedTimer parse_timer;
     HTMLFragmentParsingBehaviorSet parser_behavior;
     if (parse_declarative_shadows ==
-        Element::ParseDeclarativeShadowRoots::kParse) {
+        FragmentParserConfig::ParseDeclarativeShadowRoots::kParse) {
       parser_behavior.Put(HTMLFragmentParsingBehavior::kIncludeShadowRoots);
     }
     const bool parsed_fast_path = TryParsingHTMLFragment(
@@ -758,6 +770,72 @@
   }
   return fragment;
 }
+}  // namespace
+
+FragmentParserConfig GetFragmentParserConfig(Sanitizer::Mode mode,
+                                             const AtomicString& interface_name,
+                                             const AtomicString& property_name,
+                                             ContainerNode* context) {
+  CHECK(context->IsElementNode() || context->IsShadowRoot());
+  return {.sanitizer_mode = mode,
+          .parse_declarative_shadows =
+              FragmentParserConfig::ParseDeclarativeShadowRoots::kParse,
+          .force_html = FragmentParserConfig::ForceHtml::kForce,
+          .interface_name = interface_name,
+          .property_name = property_name,
+          .context_element = context->IsElementNode()
+                                 ? To<Element>(context)
+                                 : &To<ShadowRoot>(context)->host(),
+          .registry = context->IsElementNode()
+                          ? To<Element>(context)->customElementRegistry()
+                          : To<ShadowRoot>(context)->customElementRegistry()};
+}
+
+DocumentFragment* ParseHTMLFragment(const String& markup,
+                                    const FragmentParserConfig& config,
+                                    FragmentParserOptions options,
+                                    ExceptionState& exception_state) {
+  if (exception_state.HadException()) {
+    return nullptr;
+  }
+
+  if (RuntimeEnabledFeatures::TrustedTypesCreateParserOptionsEnabled()) {
+    auto trusted_options = TrustedTypesCheckForParserOptions(
+        options, MarkupInsertionMode::kFragment,
+        config.context_element->GetExecutionContext(), config.interface_name,
+        config.property_name, exception_state);
+    if (!trusted_options) {
+      return nullptr;
+    }
+    options = *trusted_options;
+  }
+
+  const ParserContentPolicy content_policy =
+      (RuntimeEnabledFeatures::SetHTMLCanRunScriptsEnabled() &&
+       options.run_scripts() == FragmentParserOptions::RunScripts::kRunScripts)
+          ? kAllowScriptingContentAndDoNotMarkAlreadyStarted
+          : kAllowScriptingContent;
+
+  const bool should_sanitize =
+      options.sanitizer_init() ||
+      (config.sanitizer_mode == Sanitizer::Mode::kSafe);
+
+  CHECK(!should_sanitize || RuntimeEnabledFeatures::SanitizerAPIEnabled());
+  DocumentFragment* fragment = CreateFragmentForInnerOuterHTML(
+      markup, config.context_element, content_policy,
+      config.parse_declarative_shadows, config.force_html,
+      should_sanitize ? ForceInertTemplate::kForce
+                      : ForceInertTemplate::kDontForce,
+      config.registry, exception_state);
+
+  if (fragment && should_sanitize) {
+    SanitizerAPI::SanitizeInternal(config.sanitizer_mode,
+                                   config.context_element, fragment, options,
+                                   exception_state);
+  }
+
+  return fragment;
+}
 
 DocumentFragment* CreateFragmentForTransformToFragment(
     const String& source_string,
@@ -806,42 +884,6 @@
   fragment->RemoveChild(element);
 }
 
-DocumentFragment* CreateContextualFragment(
-    const String& markup,
-    Element* element,
-    ParserContentPolicy parser_content_policy,
-    ExceptionState& exception_state) {
-  DCHECK(element);
-
-  DocumentFragment* fragment = CreateFragmentForInnerOuterHTML(
-      markup, element, parser_content_policy,
-      Element::ParseDeclarativeShadowRoots::kDontParse,
-      Element::ForceHtml::kDontForce, ForceInertTemplate::kDontForce,
-      RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled()
-          ? element->customElementRegistry()
-          : element->GetDocument().customElementRegistry(),
-      exception_state);
-  if (!fragment)
-    return nullptr;
-
-  // We need to pop <html> and <body> elements and remove <head> to
-  // accommodate folks passing complete HTML documents to make the
-  // child of an element.
-
-  Node* next_node = nullptr;
-  for (Node* node = fragment->firstChild(); node; node = next_node) {
-    next_node = node->nextSibling();
-    if (IsA<HTMLHtmlElement>(node) || IsA<HTMLHeadElement>(node) ||
-        IsA<HTMLBodyElement>(node)) {
-      auto* child_element = To<HTMLElement>(node);
-      if (Node* first_child = child_element->firstChild())
-        next_node = first_child;
-      RemoveElementPreservingChildren(fragment, child_element);
-    }
-  }
-  return fragment;
-}
-
 void ReplaceChildrenWithFragment(ContainerNode* container,
                                  DocumentFragment* fragment,
                                  ExceptionState& exception_state) {
@@ -950,6 +992,50 @@
   return document;
 }
 
+DocumentFragment* CreateContextualFragment(const String& html,
+                                           Element* element,
+                                           ExceptionState& exception_state) {
+  if (exception_state.HadException()) {
+    return nullptr;
+  }
+
+  DocumentFragment* fragment = blink::ParseHTMLFragment(
+      html,
+      {
+          .interface_name = trusted_types_names::kRange,
+          .property_name = trusted_types_names::kCreateContextualFragment,
+          .context_element = element,
+          .registry =
+              RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled()
+                  ? element->customElementRegistry()
+                  : element->GetDocument().customElementRegistry(),
+      },
+      FragmentParserOptions(FragmentParserOptions::RunScripts::kRunScripts),
+      exception_state);
+
+  if (!fragment) {
+    return nullptr;
+  }
+
+  // We need to pop <html> and <body> elements and remove <head> to
+  // accommodate folks passing complete HTML documents to make the
+  // child of an element.
+  Node* next_node = nullptr;
+  for (Node* child = fragment->firstChild(); child; child = next_node) {
+    next_node = child->nextSibling();
+    if (IsA<HTMLHtmlElement>(child) || IsA<HTMLHeadElement>(child) ||
+        IsA<HTMLBodyElement>(child)) {
+      auto* child_element = To<HTMLElement>(child);
+      if (Node* first_child = child_element->firstChild()) {
+        next_node = first_child;
+      }
+      RemoveElementPreservingChildren(fragment, child_element);
+    }
+  }
+
+  return fragment;
+}
+
 static bool ContainsStyleElements(const DocumentFragment& fragment) {
   for (const Node& node : NodeTraversal::DescendantsOf(fragment)) {
     if (IsA<HTMLStyleElement>(node) || IsA<SVGStyleElement>(node))
diff --git a/third_party/blink/renderer/core/editing/serializers/serialization.h b/third_party/blink/renderer/core/editing/serializers/serialization.h
index 67db6e9..c194f9f3 100644
--- a/third_party/blink/renderer/core/editing/serializers/serialization.h
+++ b/third_party/blink/renderer/core/editing/serializers/serialization.h
@@ -33,6 +33,8 @@
 #include "third_party/blink/renderer/core/editing/forward.h"
 #include "third_party/blink/renderer/core/editing/serializers/create_markup_options.h"
 #include "third_party/blink/renderer/core/editing/serializers/html_interchange.h"
+#include "third_party/blink/renderer/core/html/parser/fragment_parser_options.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_types_names.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -49,10 +51,6 @@
 
 enum ChildrenOnly { kIncludeNode, kChildrenOnly };
 
-// ForceInertTemplate specifies whether the HTML parser should parse into an
-// inert (non-active) template document.
-enum class ForceInertTemplate { kDontForce, kForce };
-
 using ShadowRootSet = HeapHashSet<Member<ShadowRoot>>;
 struct ShadowRootInclusion final {
   STACK_ALLOCATED();
@@ -91,22 +89,22 @@
                                                       unsigned fragment_end,
                                                       const String& base_url,
                                                       ParserContentPolicy);
-DocumentFragment* CreateFragmentForInnerOuterHTML(
-    const String&,
-    Element*,
-    ParserContentPolicy,
-    Element::ParseDeclarativeShadowRoots parse_declarative_shadows,
-    Element::ForceHtml force_html,
-    ForceInertTemplate force_inert,
-    CustomElementRegistry* registry,
-    ExceptionState&);
+DocumentFragment* ParseHTMLFragment(const String& html,
+                                    const FragmentParserConfig& config,
+                                    FragmentParserOptions options,
+                                    ExceptionState& exception_state);
+FragmentParserConfig GetFragmentParserConfig(Sanitizer::Mode mode,
+                                             const AtomicString& interface_name,
+                                             const AtomicString& property_name,
+                                             ContainerNode* context);
+
 DocumentFragment* CreateFragmentForTransformToFragment(
     const String&,
     const String& source_mime_type,
     Document& output_doc);
-DocumentFragment* CreateContextualFragment(const String&,
+
+DocumentFragment* CreateContextualFragment(const String& html,
                                            Element*,
-                                           ParserContentPolicy,
                                            ExceptionState&);
 
 bool IsPlainTextMarkup(Node*);
diff --git a/third_party/blink/renderer/core/events/event_type_names.json5 b/third_party/blink/renderer/core/events/event_type_names.json5
index 423c587..2f662f0a 100644
--- a/third_party/blink/renderer/core/events/event_type_names.json5
+++ b/third_party/blink/renderer/core/events/event_type_names.json5
@@ -86,6 +86,7 @@
     "contentvisibilityautostatechange",
     "contextlost",
     "contextmenu",
+    "contextoverflow",
     "contextrestored",
     "controllerchange",
     "cookiechange",
diff --git a/third_party/blink/renderer/core/frame/deprecation/deprecation.json5 b/third_party/blink/renderer/core/frame/deprecation/deprecation.json5
index 5d42eee..800f58b0 100644
--- a/third_party/blink/renderer/core/frame/deprecation/deprecation.json5
+++ b/third_party/blink/renderer/core/frame/deprecation/deprecation.json5
@@ -291,6 +291,15 @@
       "chrome_status_feature": 5134603979063296
     },
     {
+      "name": "LanguageModel_OnQuotaOverflow",
+      "message": "LanguageModel.onquotaoverflow is deprecated. Please use LanguageModel.oncontextoverflow instead. The LanguageModel.onquotaoverflow alias is only available in extensions.",
+      "translation_note": "Warning for using deprecated 'onquotaoverflow' event handler.",
+      "web_features": [
+        "kLanguageModel_OnQuotaOverflow"
+      ],
+      "chrome_status_feature": 5134603979063296
+    },
+    {
       "name": "LanguageModelParams",
       "message": "LanguageModel.params() is deprecated and now only available in extension contexts. The topK and temperature related fields within its result are also deprecated.",
       "translation_note": "Warning message for web developers when they call the deprecated LanguageModel.params() method.",
diff --git a/third_party/blink/renderer/core/html/anchor_element_observer.cc b/third_party/blink/renderer/core/html/anchor_element_observer.cc
deleted file mode 100644
index afc2b5f..0000000
--- a/third_party/blink/renderer/core/html/anchor_element_observer.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/html/anchor_element_observer.h"
-
-#include "third_party/blink/renderer/core/dom/id_target_observer.h"
-#include "third_party/blink/renderer/core/html/html_element.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
-
-namespace blink {
-
-namespace {
-
-class AnchorIdTargetObserver : public IdTargetObserver {
- public:
-  AnchorIdTargetObserver(const AtomicString& id,
-                         AnchorElementObserver* anchor_element_observer)
-      : IdTargetObserver(anchor_element_observer->GetSourceElement()
-                             .GetTreeScope()
-                             .EnsureIdTargetObserverRegistry(),
-                         id),
-        anchor_element_observer_(anchor_element_observer) {}
-
-  void IdTargetChanged() override { anchor_element_observer_->Notify(); }
-
-  bool SameId(const AtomicString& id) const { return id == Id(); }
-
-  void Trace(Visitor* visitor) const override {
-    visitor->Trace(anchor_element_observer_);
-    IdTargetObserver::Trace(visitor);
-  }
-
- private:
-  Member<AnchorElementObserver> anchor_element_observer_;
-};
-
-bool NeedsIdTargetObserver(Element& element) {
-  return element.IsInTreeScope() &&
-         !element.HasExplicitlySetAttrAssociatedElements(
-             html_names::kAnchorAttr) &&
-         !element.FastGetAttribute(html_names::kAnchorAttr).empty();
-}
-
-}  // namespace
-
-void AnchorElementObserver::Trace(Visitor* visitor) const {
-  visitor->Trace(source_element_);
-  visitor->Trace(current_anchor_);
-  visitor->Trace(id_target_observer_);
-  ElementRareDataField::Trace(visitor);
-}
-
-void AnchorElementObserver::Notify() {
-  Element* new_anchor = source_element_->anchorElement();
-  if (current_anchor_ != new_anchor) {
-    if (new_anchor) {
-      new_anchor->SetMayBeImplicitAnchor();
-    }
-    current_anchor_ = new_anchor;
-    if (source_element_->GetLayoutObject()) {
-      source_element_->GetLayoutObject()
-          ->SetNeedsLayoutAndFullPaintInvalidation(
-              layout_invalidation_reason::kAnchorPositioning);
-    }
-  }
-  ResetIdTargetObserverIfNeeded();
-}
-
-void AnchorElementObserver::ResetIdTargetObserverIfNeeded() {
-  if (!NeedsIdTargetObserver(*source_element_)) {
-    if (id_target_observer_) {
-      id_target_observer_->Unregister();
-      id_target_observer_ = nullptr;
-    }
-    return;
-  }
-  const AtomicString& anchor_id =
-      source_element_->FastGetAttribute(html_names::kAnchorAttr);
-  if (id_target_observer_) {
-    if (static_cast<AnchorIdTargetObserver*>(id_target_observer_.Get())
-            ->SameId(anchor_id)) {
-      // Already observing the same id target. Nothing more to do.
-      return;
-    }
-    id_target_observer_->Unregister();
-  }
-  id_target_observer_ =
-      MakeGarbageCollected<AnchorIdTargetObserver>(anchor_id, this);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/html/anchor_element_observer.h b/third_party/blink/renderer/core/html/anchor_element_observer.h
deleted file mode 100644
index 87cc7c69..0000000
--- a/third_party/blink/renderer/core/html/anchor_element_observer.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_ANCHOR_ELEMENT_OBSERVER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_ANCHOR_ELEMENT_OBSERVER_H_
-
-#include "third_party/blink/renderer/core/dom/element_rare_data_field.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/heap/member.h"
-
-namespace blink {
-
-class Element;
-class IdTargetObserver;
-
-// Tracks the value of Element::anchorElement() to help other elements know
-// whether they are used as implicit anchor elements.
-// NOTE: this class is unrelated to the <a> element.
-class AnchorElementObserver : public GarbageCollected<AnchorElementObserver>,
-                              public ElementRareDataField {
- public:
-  // This observer is placed on an element (the "source" element) that has
-  // the anchor attribute. The observer tags implicit anchors with
-  // "MayBeImplicitAnchor" on the target element.
-  explicit AnchorElementObserver(Element* source_element)
-      : source_element_(source_element) {
-    DCHECK(source_element_);
-  }
-  const Element& GetSourceElement() const { return *source_element_; }
-
-  void Notify();
-
-  void Trace(Visitor* visitor) const override;
-
- private:
-  void ResetIdTargetObserverIfNeeded();
-
-  Member<Element> source_element_;
-  Member<Element> current_anchor_;
-  Member<IdTargetObserver> id_target_observer_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_ANCHOR_ELEMENT_OBSERVER_H_
diff --git a/third_party/blink/renderer/core/html/build.gni b/third_party/blink/renderer/core/html/build.gni
index 67d1cea..0094c14 100644
--- a/third_party/blink/renderer/core/html/build.gni
+++ b/third_party/blink/renderer/core/html/build.gni
@@ -9,8 +9,6 @@
   "anchor_element_metrics_sender.h",
   "anchor_element_viewport_position_tracker.h",
   "anchor_element_viewport_position_tracker.cc",
-  "anchor_element_observer.cc",
-  "anchor_element_observer.h",
   "anchor_element_utils.cc",
   "anchor_element_utils.h",
   "blocking_attribute.cc",
@@ -605,6 +603,7 @@
   "parser/atomic_html_token.h",
   "parser/css_preload_scanner.cc",
   "parser/css_preload_scanner.h",
+  "parser/fragment_parser_options.h",
   "parser/html_attributes_ranges.h",
   "parser/html_construction_site.cc",
   "parser/html_construction_site.h",
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element.cc b/third_party/blink/renderer/core/html/forms/html_select_element.cc
index 0896fe2..09e4043 100644
--- a/third_party/blink/renderer/core/html/forms/html_select_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_select_element.cc
@@ -214,29 +214,21 @@
 }
 
 void HTMLSelectElement::UpdateUsesMenuList() {
-  if (RuntimeEnabledFeatures::SelectMobileDesktopParityEnabled()) {
-    // Choose MenuList or ListBox the same regardless of the platform:
-    // <select>                  MenuList (popup)
-    // <select size=1>           MenuList (popup)
-    // <select multiple size=1>  MenuList (popup)
-    // <select multiple>         ListBox  (in-page)
-    // <select size=4>           ListBox  (in-page)
-    // <select multiple size=4>  ListBox  (in-page)
-    if (is_multiple_) {
-      // <select multiple> does not use MenuList by default. The author must
-      // specify <select multiple size=1> to get MenuList.
-      uses_menu_list_ =
-          FastHasAttribute(html_names::kSizeAttr) ? size_ == 1 : false;
-    } else {
-      uses_menu_list_ = size_ <= 1;
-    }
-    return;
+  // Choose MenuList or ListBox the same regardless of the platform:
+  // <select>                  MenuList (popup)
+  // <select size=1>           MenuList (popup)
+  // <select multiple size=1>  MenuList (popup)
+  // <select multiple>         ListBox  (in-page)
+  // <select size=4>           ListBox  (in-page)
+  // <select multiple size=4>  ListBox  (in-page)
+  if (is_multiple_) {
+    // <select multiple> does not use MenuList by default. The author must
+    // specify <select multiple size=1> to get MenuList.
+    uses_menu_list_ =
+        FastHasAttribute(html_names::kSizeAttr) ? size_ == 1 : false;
+  } else {
+    uses_menu_list_ = size_ <= 1;
   }
-
-  if (LayoutTheme::GetTheme().DelegatesMenuListRendering())
-    uses_menu_list_ = true;
-  else
-    uses_menu_list_ = !is_multiple_ && size_ <= 1;
 }
 
 int HTMLSelectElement::ActiveSelectionEndListIndex() const {
@@ -1007,7 +999,6 @@
 void HTMLSelectElement::SelectOptionFromPopoverPickerOrBaseListbox(
     HTMLOptionElement* option) {
   if (!UsesMenuList() || IsMultiple()) {
-    CHECK(RuntimeEnabledFeatures::SelectMobileDesktopParityEnabled());
     option->SetSelectedState(!option->Selected());
     option->SetDirty(true);
     if (!IsMultiple()) {
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element_test.cc b/third_party/blink/renderer/core/html/forms/html_select_element_test.cc
index 46f5caed..c39ce64 100644
--- a/third_party/blink/renderer/core/html/forms/html_select_element_test.cc
+++ b/third_party/blink/renderer/core/html/forms/html_select_element_test.cc
@@ -70,21 +70,14 @@
     auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
     return select->InnerElement().textContent();
   }
-
- private:
-  bool original_delegates_flag_;
 };
 
 void HTMLSelectElementTest::SetUp() {
   PageTestBase::SetUp();
   GetDocument().SetMimeType(AtomicString("text/html"));
-  original_delegates_flag_ =
-      LayoutTheme::GetTheme().DelegatesMenuListRendering();
 }
 
 void HTMLSelectElementTest::TearDown() {
-  LayoutTheme::GetTheme().SetDelegatesMenuListRenderingForTesting(
-      original_delegates_flag_);
   PageTestBase::TearDown();
 }
 
@@ -555,7 +548,6 @@
 // crbug.com/1060039
 TEST_F(HTMLSelectElementTest, SelectMultipleOptions) {
   GetDocument().GetSettings()->SetScriptEnabled(true);
-  LayoutTheme::GetTheme().SetDelegatesMenuListRenderingForTesting(true);
 
   // Select the same set of options.
   {
diff --git a/third_party/blink/renderer/core/html/forms/html_text_area_element.cc b/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
index 3cae78b..6ea0c500 100644
--- a/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
@@ -74,12 +74,14 @@
 
 using mojom::blink::FormControlType;
 
-static const unsigned kDefaultRows = 2;
-static const unsigned kDefaultCols = 20;
+namespace {
 
-static bool is_default_font_prewarmed_ = false;
+constexpr unsigned kDefaultRows = 2;
+constexpr unsigned kDefaultCols = 20;
 
-static inline unsigned ComputeLengthForAPIValue(const String& text) {
+bool g_is_default_font_prewarmed = false;
+
+inline unsigned ComputeLengthForAPIValue(const String& text) {
   unsigned length = text.length();
   unsigned crlf_count = 0;
   for (unsigned i = 0; i < length; ++i) {
@@ -89,6 +91,8 @@
   return text.length() - crlf_count;
 }
 
+}  // namespace
+
 HTMLTextAreaElement::HTMLTextAreaElement(Document& document)
     : TextControlElement(html_names::kTextareaTag, document),
       rows_(kDefaultRows),
@@ -98,14 +102,14 @@
       is_placeholder_visible_(false) {
   EnsureUserAgentShadowRoot();
 
-  if (!is_default_font_prewarmed_) {
+  if (!g_is_default_font_prewarmed) {
     if (Settings* settings = document.GetSettings()) {
       // Prewarm 'monospace', the default font family for `<textarea>`. The
       // default language should be fine for this purpose because most users set
       // the same family for all languages.
       FontCache::PrewarmFamily(settings->GetGenericFontFamilySettings().Fixed(
           LayoutLocale::GetDefault().GetScript()));
-      is_default_font_prewarmed_ = true;
+      g_is_default_font_prewarmed = true;
     }
   }
 }
diff --git a/third_party/blink/renderer/core/html/forms/select_type.cc b/third_party/blink/renderer/core/html/forms/select_type.cc
index 1e9b4ea..d267c55 100644
--- a/third_party/blink/renderer/core/html/forms/select_type.cc
+++ b/third_party/blink/renderer/core/html/forms/select_type.cc
@@ -679,19 +679,20 @@
 }
 
 bool MenuListSelectType::PickerIsPopover() const {
-  if (select_->IsMultiple()) {
-    if (!RuntimeEnabledFeatures::SelectMobileDesktopParityEnabled()) {
-      return false;
-    }
-    if (IsAppearanceBasePicker()) {
-      return true;
-    }
-    // In appearance:auto/none mode, we use the native <select multiple> popup
-    // if available (only on Android right now). Otherwise, we keep using the
-    // popover.
-    return !LayoutTheme::GetTheme().DelegatesMenuListRendering();
+  if (IsAppearanceBasePicker()) {
+    return true;
   }
-  return IsAppearanceBasePicker();
+  if (select_->IsMultiple()) {
+    // In appearance:auto/none mode, we use the native <select multiple> popup
+    // if available (only on Android right now). In appearance:base mode, we
+    // keep using the popover.
+#if BUILDFLAG(IS_ANDROID)
+    return false;
+#else
+    return true;
+#endif
+  }
+  return false;
 }
 
 void MenuListSelectType::SetIsAppearanceBasePickerForDisplayNone(bool value) {
@@ -712,16 +713,6 @@
 }
 
 void MenuListSelectType::ShowPopup(PopupMenu::ShowEventType type) {
-  if (LayoutTheme::GetTheme().DelegatesMenuListRendering() &&
-      select_->IsMultiple() &&
-      !select_->FastHasAttribute(html_names::kSizeAttr)) {
-    // If this UseCounter is low, then we could consider not delegating MenuList
-    // rendering for <select multiple> when no size attribute is present.
-    // https://issues.chromium.org/issues/357649033
-    UseCounter::Count(select_->GetDocument(),
-                      WebFeature::kSelectMultipleShowPopup);
-  }
-
   if (PopupIsVisible()) {
     return;
   }
diff --git a/third_party/blink/renderer/core/html/html_attribute_names.json5 b/third_party/blink/renderer/core/html/html_attribute_names.json5
index ceae0c12..2b83a49 100644
--- a/third_party/blink/renderer/core/html/html_attribute_names.json5
+++ b/third_party/blink/renderer/core/html/html_attribute_names.json5
@@ -21,7 +21,6 @@
     "allowfullscreen",
     "allowpaymentrequest",
     "alt",
-    "anchor",
     "archive",
     "as",
     "async",
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc
index 3491189..b5a00b5 100644
--- a/third_party/blink/renderer/core/html/html_element.cc
+++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -82,7 +82,6 @@
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
-#include "third_party/blink/renderer/core/html/anchor_element_observer.h"
 #include "third_party/blink/renderer/core/html/custom/custom_element.h"
 #include "third_party/blink/renderer/core/html/custom/custom_element_registry.h"
 #include "third_party/blink/renderer/core/html/custom/element_internals.h"
@@ -326,7 +325,7 @@
 }
 
 bool HTMLElement::IsPresentationAttribute(const QualifiedName& name) const {
-  if (name == html_names::kAlignAttr || name == html_names::kAnchorAttr ||
+  if (name == html_names::kAlignAttr ||
       name == html_names::kContenteditableAttr ||
       name == html_names::kHiddenAttr || name == html_names::kLangAttr ||
       name.Matches(xml_names::kLangAttr) ||
@@ -355,11 +354,6 @@
       AddPropertyToPresentationAttributeStyle(style, CSSPropertyID::kTextAlign,
                                               value);
     }
-  } else if (name == html_names::kAnchorAttr) {
-    if (RuntimeEnabledFeatures::HTMLAnchorAttributeEnabled()) {
-      AddPropertyToPresentationAttributeStyle(
-          style, CSSPropertyID::kPositionAnchor, CSSValueID::kAuto);
-    }
   } else if (name == html_names::kContenteditableAttr) {
     AtomicString lower_value = value.LowerASCII();
     if (lower_value.empty() || lower_value == keywords::kTrue) {
@@ -2395,9 +2389,7 @@
   // 1. DOM tree ancestor.
   check_ancestor(
       FlatTreeTraversal::ParentElement(new_popover_or_top_layer_element));
-  // 2. Anchor attribute.
-  check_ancestor(new_popover_or_top_layer_element.anchorElement());
-  // 3. Invoker to popover
+  // 2. Invoker to popover
   check_ancestor(new_popovers_invoker);
   return topmost_popover_ancestor;
 }
diff --git a/third_party/blink/renderer/core/html/html_element_test.cc b/third_party/blink/renderer/core/html/html_element_test.cc
index c63f9939..12335ee 100644
--- a/third_party/blink/renderer/core/html/html_element_test.cc
+++ b/third_party/blink/renderer/core/html/html_element_test.cc
@@ -256,119 +256,6 @@
       GetDocument().GetPage()->Animator().has_inline_style_mutation_for_test());
 }
 
-TEST_F(HTMLElementTest, MayBeImplicitAnchor) {
-  SetBodyInnerHTML(R"HTML(
-    <div id="anchor1"></div>
-    <div id="anchor2"></div>
-    <div id="target" anchor="anchor1"></div>
-  )HTML");
-
-  Element* anchor1 = GetDocument().getElementById(AtomicString("anchor1"));
-  Element* anchor2 = GetDocument().getElementById(AtomicString("anchor2"));
-  HTMLElement* target =
-      To<HTMLElement>(GetDocument().getElementById(AtomicString("target")));
-
-  EXPECT_EQ(target->anchorElement(), anchor1);
-  EXPECT_TRUE(anchor1->MayBeImplicitAnchor());
-  EXPECT_FALSE(anchor2->MayBeImplicitAnchor());
-
-  target->setAttribute(html_names::kAnchorAttr, AtomicString("anchor2"));
-
-  EXPECT_EQ(target->anchorElement(), anchor2);
-  EXPECT_TRUE(anchor1->MayBeImplicitAnchor());
-  EXPECT_TRUE(anchor2->MayBeImplicitAnchor());
-
-  target->removeAttribute(html_names::kAnchorAttr);
-
-  EXPECT_FALSE(target->anchorElement());
-  EXPECT_TRUE(anchor1->MayBeImplicitAnchor());
-  EXPECT_TRUE(anchor2->MayBeImplicitAnchor());
-}
-
-TEST_F(HTMLElementTest, MayBeImplicitAnchorViaElementAttr) {
-  SetBodyInnerHTML(R"HTML(
-    <div id="anchor1"></div>
-    <div id="anchor2"></div>
-    <div id="target" anchor="anchor1"></div>
-  )HTML");
-
-  Element* anchor1 = GetDocument().getElementById(AtomicString("anchor1"));
-  Element* anchor2 = GetDocument().getElementById(AtomicString("anchor2"));
-  HTMLElement* target =
-      To<HTMLElement>(GetDocument().getElementById(AtomicString("target")));
-
-  EXPECT_EQ(target->anchorElement(), anchor1);
-  EXPECT_TRUE(anchor1->MayBeImplicitAnchor());
-  EXPECT_FALSE(anchor2->MayBeImplicitAnchor());
-
-  target->setAnchorElementForBinding(anchor2);
-
-  EXPECT_EQ(target->anchorElement(), anchor2);
-  EXPECT_TRUE(anchor1->MayBeImplicitAnchor());
-  EXPECT_TRUE(anchor2->MayBeImplicitAnchor());
-
-  target->setAnchorElementForBinding(nullptr);
-
-  EXPECT_FALSE(target->anchorElement());
-  EXPECT_TRUE(anchor1->MayBeImplicitAnchor());
-  EXPECT_TRUE(anchor2->MayBeImplicitAnchor());
-
-  target->setAttribute(html_names::kAnchorAttr, AtomicString("anchor1"));
-
-  EXPECT_EQ(target->anchorElement(), anchor1);
-  EXPECT_TRUE(anchor1->MayBeImplicitAnchor());
-  EXPECT_TRUE(anchor2->MayBeImplicitAnchor());
-}
-
-TEST_F(HTMLElementTest, ImplicitAnchorIdChange) {
-  SetBodyInnerHTML(R"HTML(
-    <div id="anchor1"></div>
-    <div id="anchor2"></div>
-    <div id="target" anchor="anchor1"></div>
-  )HTML");
-
-  Element* anchor1 = GetDocument().getElementById(AtomicString("anchor1"));
-  Element* anchor2 = GetDocument().getElementById(AtomicString("anchor2"));
-  HTMLElement* target =
-      To<HTMLElement>(GetDocument().getElementById(AtomicString("target")));
-
-  EXPECT_EQ(target->anchorElement(), anchor1);
-  EXPECT_TRUE(anchor1->MayBeImplicitAnchor());
-  EXPECT_FALSE(anchor2->MayBeImplicitAnchor());
-
-  anchor1->setAttribute(html_names::kIdAttr, AtomicString("anchor2"));
-  anchor2->setAttribute(html_names::kIdAttr, AtomicString("anchor1"));
-
-  EXPECT_EQ(target->anchorElement(), anchor2);
-  EXPECT_TRUE(anchor1->MayBeImplicitAnchor());
-  EXPECT_TRUE(anchor2->MayBeImplicitAnchor());
-}
-
-TEST_F(HTMLElementTest, ImplicitlyAnchorElementConnected) {
-  SetBodyInnerHTML("<div id=anchor></div>");
-
-  Element* anchor = GetDocument().getElementById(AtomicString("anchor"));
-
-  HTMLElement* target1 = To<HTMLElement>(
-      GetDocument().CreateElementForBinding(AtomicString("div")));
-  target1->setAttribute(html_names::kAnchorAttr, AtomicString("anchor"));
-
-  HTMLElement* target2 = To<HTMLElement>(
-      GetDocument().CreateElementForBinding(AtomicString("div")));
-  target2->setAnchorElementForBinding(anchor);
-
-  EXPECT_FALSE(target1->anchorElement());
-  EXPECT_FALSE(target2->anchorElement());
-  EXPECT_FALSE(anchor->MayBeImplicitAnchor());
-
-  GetDocument().body()->appendChild(target1);
-  GetDocument().body()->appendChild(target2);
-
-  EXPECT_EQ(target1->anchorElement(), anchor);
-  EXPECT_EQ(target2->anchorElement(), anchor);
-  EXPECT_TRUE(anchor->MayBeImplicitAnchor());
-}
-
 TEST_F(HTMLElementTest, PopoverTopLayerRemovalTiming) {
   SetBodyInnerHTML(R"HTML(
     <div id="target" popover></div>
diff --git a/third_party/blink/renderer/core/html/html_stream.cc b/third_party/blink/renderer/core/html/html_stream.cc
index 8d38282..cf769e36 100644
--- a/third_party/blink/renderer/core/html/html_stream.cc
+++ b/third_party/blink/renderer/core/html/html_stream.cc
@@ -9,6 +9,8 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/html/custom/custom_element_registry.h"
+#include "third_party/blink/renderer/core/html/parser/fragment_parser_options.h"
 #include "third_party/blink/renderer/core/html/parser/html_document_parser.h"
 #include "third_party/blink/renderer/core/sanitizer/sanitizer_api.h"
 #include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
@@ -31,8 +33,19 @@
 class HTMLSink : public UnderlyingSinkBase {
  public:
   explicit HTMLSink(ContainerNode& new_target,
-                    const TrustedParserOptions* new_options)
-      : target(new_target), options(new_options) {
+                    FragmentParserOptions new_options)
+      : target(new_target),
+
+        sanitizer(SanitizerAPI::CreateStreamingSanitizerInternal(
+            new_options,
+            &new_target,
+            ASSERT_NO_EXCEPTION)),
+        parser_content_policy(
+            new_options.run_scripts() ==
+                    FragmentParserOptions::RunScripts::kRunScripts
+                ? ParserContentPolicy::
+                      kAllowScriptingContentAndDoNotMarkAlreadyStarted
+                : ParserContentPolicy::kAllowScriptingContent) {
     CHECK(target->IsElementNode() || target->IsShadowRoot());
   }
 
@@ -40,7 +53,7 @@
     UnderlyingSinkBase::Trace(visitor);
     visitor->Trace(target);
     visitor->Trace(parser);
-    visitor->Trace(options);
+    visitor->Trace(sanitizer);
   }
 
   ScriptPromise<IDLUndefined> start(ScriptState* script_state,
@@ -53,24 +66,16 @@
       }
     }
 
-    SetHTMLUnsafeOptions* unsafe_options =
-        SetHTMLUnsafeOptions::Create(script_state->GetIsolate());
-    unsafe_options->setSanitizer(options->sanitizer());
-    unsafe_options->setRunScripts(options->runScripts());
+    CustomElementRegistry* registry = context_element->customElementRegistry();
+    if (!registry) {
+      registry = context_element->GetDocument().customElementRegistry();
+    }
 
     // TODO(nrosenthal): support safe sanitizer.
-    StreamingSanitizer* sanitizer =
-        SanitizerAPI::CreateStreamingSanitizerUnsafeInternal(
-            unsafe_options, target, exception_state);
     // FIXME(nrosenthal): support more methods. This currently assumes "append".
-    // FIXME(nrosenthal): custom element registry support?
     parser = MakeGarbageCollected<HTMLDocumentParser>(
-        target, context_element,
-        options->runScripts()
-            ? ParserContentPolicy::
-                  kAllowScriptingContentAndDoNotMarkAlreadyStarted
-            : ParserContentPolicy::kAllowScriptingContent,
-        ParserPrefetchPolicy::kDisallowPrefetching, /*registry*/ nullptr,
+        target, context_element, parser_content_policy,
+        ParserPrefetchPolicy::kDisallowPrefetching, registry,
         /*sanitizer*/ sanitizer);
 
     return ToResolvedUndefinedPromise(script_state);
@@ -112,28 +117,30 @@
 
   Member<ContainerNode> target;
   Member<DocumentParser> parser;
-  Member<const TrustedParserOptions> options;
+  Member<StreamingSanitizer> sanitizer;
+  ParserContentPolicy parser_content_policy;
 };
 }  // namespace
 
 // static
-WritableStream* HTMLStream::Create(
-    ScriptState* script_state,
-    ContainerNode* target,
-    const V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions*
-        options_or_trusted_options,
-    const AtomicString& property_name,
-    ExceptionState& exception_state) {
+WritableStream* HTMLStream::Create(ScriptState* script_state,
+                                   ContainerNode* target,
+                                   FragmentParserOptions options,
+                                   const AtomicString& property_name,
+                                   ExceptionState& exception_state) {
   CHECK(RuntimeEnabledFeatures::DocumentPatchingEnabled());
-  const TrustedParserOptions* options = TrustedTypesCheckForParserOptions(
-      options_or_trusted_options, target->GetExecutionContext(),
-      target->InterfaceName(), property_name, exception_state);
-  if (!options) {
-    CHECK(exception_state.HadException());
+
+  std::optional<FragmentParserOptions> trusted_options =
+      TrustedTypesCheckForParserOptions(
+          options, MarkupInsertionMode::kStream, target->GetExecutionContext(),
+          target->InterfaceName(), property_name, exception_state);
+
+  if (!trusted_options) {
     return nullptr;
   }
 
-  HTMLSink* sink = MakeGarbageCollected<HTMLSink>(*target, options);
+  HTMLSink* sink = MakeGarbageCollected<HTMLSink>(*target, *trusted_options);
   return WritableStream::CreateWithCountQueueingStrategy(script_state, sink, 1);
 }
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_stream.h b/third_party/blink/renderer/core/html/html_stream.h
index e97c5a2b..92e6f39 100644
--- a/third_party/blink/renderer/core/html/html_stream.h
+++ b/third_party/blink/renderer/core/html/html_stream.h
@@ -7,22 +7,21 @@
 
 namespace blink {
 class AtomicString;
+class FragmentParserOptions;
 class ContainerNode;
 class ExceptionState;
 class ScriptState;
-class V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions;
 class WritableStream;
 
 // This creates a Writable stream that takes string and inserts them into an
 // existing element or shadow root.
 class HTMLStream {
  public:
-  static WritableStream* Create(
-      ScriptState*,
-      ContainerNode* target,
-      const V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions* options,
-      const AtomicString& property_name,
-      ExceptionState&);
+  static WritableStream* Create(ScriptState*,
+                                ContainerNode* target,
+                                FragmentParserOptions options,
+                                const AtomicString& property_name,
+                                ExceptionState&);
 };
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/html/parser/fragment_parser_options.h b/third_party/blink/renderer/core/html/parser/fragment_parser_options.h
new file mode 100644
index 0000000..21913f7
--- /dev/null
+++ b/third_party/blink/renderer/core/html/parser/fragment_parser_options.h
@@ -0,0 +1,116 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_FRAGMENT_PARSER_OPTIONS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_FRAGMENT_PARSER_OPTIONS_H_
+
+#include "base/memory/stack_allocated.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_set_html_options.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_set_html_unsafe_options.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_sethtmloptions_trustedparseroptions.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_sethtmlunsafeoptions_trustedparseroptions.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/container_node.h"
+#include "third_party/blink/renderer/core/sanitizer/sanitizer.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_parser_options.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+
+namespace blink {
+
+class CustomElementRegistry;
+class V8UnionSanitizerOrSanitizerConfigOrSanitizerPresets;
+
+class CORE_EXPORT FragmentParserConfig {
+  STACK_ALLOCATED();
+
+ public:
+  enum class ParseDeclarativeShadowRoots {
+    kDontParse = 0,
+    kParse = 1,
+  };
+  // ForceHtml specifies whether the HTML parser should be used when parsing
+  // markup even if we are in an XML document.
+  enum class ForceHtml {
+    kDontForce = 0,
+    kForce = 1,
+  };
+
+  Sanitizer::Mode sanitizer_mode = Sanitizer::Mode::kUnsafe;
+  ParseDeclarativeShadowRoots parse_declarative_shadows =
+      ParseDeclarativeShadowRoots::kDontParse;
+  ForceHtml force_html = ForceHtml::kDontForce;
+  AtomicString interface_name = g_empty_atom;
+  AtomicString property_name = g_empty_atom;
+  Element* context_element = nullptr;
+  CustomElementRegistry* registry = nullptr;
+};
+
+class CORE_EXPORT FragmentParserOptions {
+  STACK_ALLOCATED();
+
+ public:
+  enum class RunScripts { kRunScripts, kDontRunScripts };
+  enum class TrustMode { kTrusted, kUntrusted };
+
+  FragmentParserOptions() = default;
+  explicit FragmentParserOptions(RunScripts run_scripts)
+      : run_scripts_(run_scripts) {}
+  FragmentParserOptions(const FragmentParserOptions&) = default;
+  FragmentParserOptions& operator=(const FragmentParserOptions&) = default;
+  explicit FragmentParserOptions(TrustedParserOptions* options)
+      : trust_mode_(TrustMode::kTrusted),
+        run_scripts_(options->runScripts() ? RunScripts::kRunScripts
+                                           : RunScripts::kDontRunScripts),
+        sanitizer_init_(options->sanitizer()) {}
+
+  explicit FragmentParserOptions(SetHTMLUnsafeOptions* options)
+      : run_scripts_(options->runScripts() ? RunScripts::kRunScripts
+                                           : RunScripts::kDontRunScripts),
+        sanitizer_init_(options->sanitizer()) {}
+
+  explicit FragmentParserOptions(SetHTMLOptions* options)
+      : sanitizer_init_(options->sanitizer()) {}
+
+  static FragmentParserOptions From(
+      const V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions* options) {
+    switch (options->GetContentType()) {
+      case V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions::ContentType::
+          kSetHTMLUnsafeOptions:
+        return FragmentParserOptions(options->GetAsSetHTMLUnsafeOptions());
+      case V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions::ContentType::
+          kTrustedParserOptions:
+        return FragmentParserOptions(options->GetAsTrustedParserOptions());
+    }
+  }
+
+  static FragmentParserOptions From(
+      const V8UnionSetHTMLOptionsOrTrustedParserOptions* options) {
+    switch (options->GetContentType()) {
+      case V8UnionSetHTMLOptionsOrTrustedParserOptions::ContentType::
+          kSetHTMLOptions:
+        return FragmentParserOptions(options->GetAsSetHTMLOptions());
+      case V8UnionSetHTMLOptionsOrTrustedParserOptions::ContentType::
+          kTrustedParserOptions:
+        return FragmentParserOptions(options->GetAsTrustedParserOptions());
+    }
+  }
+
+  TrustMode trust_mode() const { return trust_mode_; }
+  RunScripts run_scripts() const { return run_scripts_; }
+  V8UnionSanitizerOrSanitizerConfigOrSanitizerPresets* sanitizer_init() const {
+    return sanitizer_init_;
+  }
+
+ private:
+  TrustMode trust_mode_ = TrustMode::kUntrusted;
+  RunScripts run_scripts_ = RunScripts::kDontRunScripts;
+  V8UnionSanitizerOrSanitizerConfigOrSanitizerPresets* sanitizer_init_ =
+      nullptr;
+};
+
+}  // namespace blink
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_FRAGMENT_PARSER_OPTIONS_H_
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.cc b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
index 89a85e51..2d0cd1ec 100644
--- a/third_party/blink/renderer/core/html/parser/html_document_parser.cc
+++ b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
@@ -1807,13 +1807,13 @@
     return false;
   }
 
-  if (RuntimeEnabledFeatures::AllowPreloadingWithCSPMetaTagEnabled()) {
-    CHECK_GE(seen_csp_meta_tags_, 0);
-    if (!seen_csp_meta_tags_) {
-      // No CSP meta tags seen - Early return allowing preloads.
-      return true;
-    }
+  CHECK_GE(seen_csp_meta_tags_, 0);
+  if (!seen_csp_meta_tags_) {
+    // No CSP meta tags seen - Early return allowing preloads.
+    return true;
+  }
 
+  if (RuntimeEnabledFeatures::AllowPreloadingWithCSPMetaTagEnabled()) {
     Document* document = GetDocument();
     if (!document) {
       // Seen CSP tag, but there is no document to check the CSP (detach()
@@ -1836,9 +1836,9 @@
     // Only allows preloads if all seen meta tags have been processed.
     return static_cast<int>(csp->GetParsedPolicies().size()) ==
            seen_csp_meta_tags_;
+  } else {
+    return false;
   }
-
-  return true;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
index eaecf4ad5..da6612da 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
@@ -1267,7 +1267,7 @@
       // Don't preload anything if a CSP meta tag is found. We should rarely
       // find them here because the HTMLPreloadScanner is only used for the
       // synchronous parsing path.
-      CHECK(csp_meta_tag_count >= 0);
+      CHECK_GE(csp_meta_tag_count, 0);
       if (csp_meta_tag_count) {
         // Reset the tokenizer, to avoid re-scanning tokens that we are about to
         // start parsing.
diff --git a/third_party/blink/renderer/core/html/resources/html.css b/third_party/blink/renderer/core/html/resources/html.css
index 4da8d388..766d14a 100644
--- a/third_party/blink/renderer/core/html/resources/html.css
+++ b/third_party/blink/renderer/core/html/resources/html.css
@@ -1706,14 +1706,6 @@
     }
 }
 
-@supports blink-feature(HTMLAnchorAttribute) {
-    /* Popovers using anchor positioning get their inset properties reset, to make
-    * it easier to position them. */
-    [popover][anchor] {
-        inset:auto;
-    }
-}
-
 slot {
     display: contents;
 }
@@ -1830,91 +1822,47 @@
 
 /* noscript is handled internally, as it depends on settings. */
 
-@supports not blink-feature(SelectMobileDesktopParity) {
-  select:not(:-internal-list-box):not([multiple]) {
-    font: -internal-auto-base(-webkit-small-control, inherit);
-    text-shadow: -internal-auto-base(none, inherit);
-    text-transform: -internal-auto-base(none, initial);
-    text-rendering: -internal-auto-base(auto, inherit);
-    letter-spacing: -internal-auto-base(normal, inherit);
-    word-spacing: -internal-auto-base(normal, inherit);
-    text-align: -internal-auto-base(start, initial);
-    text-indent: -internal-auto-base(0px, initial);
-    -webkit-rtl-ordering: -internal-auto-base(logical, inherit);
-    cursor: -internal-auto-base(default, inherit);
-    white-space: -internal-auto-base(pre, inherit);
-    /* This text-autospace rule won't work because it is set with !important
-     * earlier in the UA stylesheet. After merging with the rest of the UA
-     * style rules when removing the CustomizableSelect flag, it should start
-     * to work. */
-    text-autospace: -internal-auto-base(no-autospace !important, inherit);
-    color: -internal-auto-base(FieldText, inherit);
-    background-color: -internal-auto-base(Field, transparent);
-    border: 1px solid -internal-auto-base(light-dark(#767676, #858585), currentColor);
-    padding-block: -internal-auto-base(0, 0.25em);
-    padding-inline: -internal-auto-base(0, 0.5em);
+/* These styles are identical to the not blink-feature block above, except
+ * that the :not([multiple]) part is removed. */
+select:not(:-internal-list-box) {
+  font: -internal-auto-base(-webkit-small-control, inherit);
+  text-shadow: -internal-auto-base(none, inherit);
+  text-transform: -internal-auto-base(none, initial);
+  text-rendering: -internal-auto-base(auto, inherit);
+  letter-spacing: -internal-auto-base(normal, inherit);
+  word-spacing: -internal-auto-base(normal, inherit);
+  text-align: -internal-auto-base(start, initial);
+  text-indent: -internal-auto-base(0px, initial);
+  -webkit-rtl-ordering: -internal-auto-base(logical, inherit);
+  cursor: -internal-auto-base(default, inherit);
+  white-space: -internal-auto-base(pre, inherit);
+  /* This text-autospace rule won't work because it is set with !important
+   * earlier in the UA stylesheet. After merging with the rest of the UA
+   * style rules when removing the CustomizableSelect flag, it should start
+   * to work. */
+  text-autospace: -internal-auto-base(no-autospace !important, inherit);
+  color: -internal-auto-base(FieldText, inherit);
+  background-color: -internal-auto-base(Field, transparent);
+  border: 1px solid -internal-auto-base(light-dark(#767676, #858585), currentColor);
+  padding-block: -internal-auto-base(0, 0.25em);
+  padding-inline: -internal-auto-base(0, 0.5em);
 
-    /* min-size rules ensure that we meet accessibility guidelines for minimum target size.
-     * https://github.com/openui/open-ui/issues/1026
-     * https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html */
-    /* TODO(crbug.com/1511354): This might be able to be combined with the
-     * default select option rules at some point. This should be re-evaluated
-     * before StylableSelect is shipped. */
-    min-inline-size: -internal-auto-base(auto, calc-size(auto, max(size, 24px)));
-    /* The 1lh here makes sure that options with no text still make the button
-     * have the same height as options with text. */
-    min-block-size: -internal-auto-base(auto, calc-size(auto, max(size, 24px, 1lh)));
+  /* min-size rules ensure that we meet accessibility guidelines for minimum target size.
+   * https://github.com/openui/open-ui/issues/1026
+   * https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html */
+  /* TODO(crbug.com/41483940): This might be able to be combined with the
+   * default select option rules at some point. This should be re-evaluated
+   * before StylableSelect is shipped. */
+  min-inline-size: -internal-auto-base(auto, calc-size(auto, max(size, 24px)));
+  /* The 1lh here makes sure that options with no text still make the button
+   * have the same height as options with text. */
+  min-block-size: -internal-auto-base(auto, calc-size(auto, max(size, 24px, 1lh)));
 
-    gap: -internal-auto-base(initial, 0.5em);
-    border-radius: -internal-auto-base(0, 0.5em);
-    align-items: -internal-auto-base(center, unset);
-    /* https://github.com/whatwg/html/issues/10876 */
-    user-select: -internal-auto-base(auto, none);
-  }
-}
-@supports blink-feature(SelectMobileDesktopParity) {
-  /* These styles are identical to the not blink-feature block above, except
-   * that the :not([multiple]) part is removed. */
-  select:not(:-internal-list-box) {
-    font: -internal-auto-base(-webkit-small-control, inherit);
-    text-shadow: -internal-auto-base(none, inherit);
-    text-transform: -internal-auto-base(none, initial);
-    text-rendering: -internal-auto-base(auto, inherit);
-    letter-spacing: -internal-auto-base(normal, inherit);
-    word-spacing: -internal-auto-base(normal, inherit);
-    text-align: -internal-auto-base(start, initial);
-    text-indent: -internal-auto-base(0px, initial);
-    -webkit-rtl-ordering: -internal-auto-base(logical, inherit);
-    cursor: -internal-auto-base(default, inherit);
-    white-space: -internal-auto-base(pre, inherit);
-    /* This text-autospace rule won't work because it is set with !important
-     * earlier in the UA stylesheet. After merging with the rest of the UA
-     * style rules when removing the CustomizableSelect flag, it should start
-     * to work. */
-    text-autospace: -internal-auto-base(no-autospace !important, inherit);
-    color: -internal-auto-base(FieldText, inherit);
-    background-color: -internal-auto-base(Field, transparent);
-    border: 1px solid -internal-auto-base(light-dark(#767676, #858585), currentColor);
-    padding-block: -internal-auto-base(0, 0.25em);
-    padding-inline: -internal-auto-base(0, 0.5em);
-
-    /* min-size rules ensure that we meet accessibility guidelines for minimum target size.
-     * https://github.com/openui/open-ui/issues/1026
-     * https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html */
-    /* TODO(crbug.com/1511354): This might be able to be combined with the
-     * default select option rules at some point. This should be re-evaluated
-     * before StylableSelect is shipped. */
-    min-inline-size: -internal-auto-base(auto, calc-size(auto, max(size, 24px)));
-    /* The 1lh here makes sure that options with no text still make the button
-     * have the same height as options with text. */
-    min-block-size: -internal-auto-base(auto, calc-size(auto, max(size, 24px, 1lh)));
-
-    gap: -internal-auto-base(initial, 0.5em);
-    border-radius: -internal-auto-base(0, 0.5em);
-    align-items: -internal-auto-base(center, unset);
-    /* https://github.com/whatwg/html/issues/10876 */
-    user-select: -internal-auto-base(auto, none);
-  }
+  gap: -internal-auto-base(initial, 0.5em);
+  border-radius: -internal-auto-base(0, 0.5em);
+  align-items: -internal-auto-base(center, unset);
+  /* https://github.com/whatwg/html/issues/10876 */
+  user-select: -internal-auto-base(auto, none);
 }
 @supports blink-feature(CustomizableSelectListbox) {
   select {
@@ -2008,134 +1956,72 @@
   }
 }
 
-@supports not blink-feature(SelectMobileDesktopParity) {
-  select:not(:-internal-list-box):not([multiple])::picker(select) {
-    box-sizing: border-box;
-    border: 1px solid;
-    padding: 0;
-    color: -internal-auto-base(inherit, CanvasText);
-    background-color: Canvas;
-    margin: 0;
-    inset: auto;
-    min-inline-size: anchor-size(self-inline);
-    /* TODO(crbug.com/409942762): Consider removing -internal-auto-base() here
-     * if underlying performance issues with lh units are fixed. */
-    min-block-size: -internal-auto-base(0, 1lh);
-    /* Go to the edge of the viewport, and add scrollbars if needed. */
-    max-block-size: stretch;
-    overflow: auto;
-    /* Below and span-right, by default. */
-    position-area: block-end span-inline-end;
-    position-try-order: most-block-size;
-    position-try-fallbacks:
-        block-start span-inline-end,   /* First try above and span-right. */
-        block-end span-inline-start,   /* Then below but span-left. */
-        block-start span-inline-start; /* Then above and span-left. */
-  }
-}
-@supports blink-feature(SelectMobileDesktopParity) {
-  select:not(:-internal-list-box)::picker(select) {
-    box-sizing: border-box;
-    border: 1px solid -internal-auto-base(light-dark(#767676, #858585), currentColor);
-    border-radius: -internal-auto-base(2px, 0);
-    padding: 0;
-    color: -internal-auto-base(inherit, CanvasText);
-    background-color: Canvas;
-    margin: 0;
-    inset: auto;
-    min-inline-size: anchor-size(self-inline);
-    /* TODO(crbug.com/409942762): Consider removing -internal-auto-base() here
-     * if underlying performance issues with lh units are fixed. */
-    min-block-size: -internal-auto-base(0, 1lh);
-    /* Go to the edge of the viewport, and add scrollbars if needed. */
-    max-block-size: stretch;
-    overflow: auto;
-    /* Below and span-right, by default. */
-    position-area: block-end span-inline-end;
-    position-try-order: most-block-size;
-    position-try-fallbacks:
-      block-start span-inline-end,
-      block-end span-inline-start,
-      block-start span-inline-start;
-  }
+select:not(:-internal-list-box)::picker(select) {
+  box-sizing: border-box;
+  border: 1px solid -internal-auto-base(light-dark(#767676, #858585), currentColor);
+  border-radius: -internal-auto-base(2px, 0);
+  padding: 0;
+  color: -internal-auto-base(inherit, CanvasText);
+  background-color: Canvas;
+  margin: 0;
+  inset: auto;
+  min-inline-size: anchor-size(self-inline);
+  /* TODO(crbug.com/409942762): Consider removing -internal-auto-base() here
+   * if underlying performance issues with lh units are fixed. */
+  min-block-size: -internal-auto-base(0, 1lh);
+  /* Go to the edge of the viewport, and add scrollbars if needed. */
+  max-block-size: stretch;
+  overflow: auto;
+  /* Below and span-right, by default. */
+  position-area: block-end span-inline-end;
+  position-try-order: most-block-size;
+  position-try-fallbacks:
+    block-start span-inline-end,
+    block-end span-inline-start,
+    block-start span-inline-start;
 }
 
-@supports not blink-feature(SelectMobileDesktopParity) {
-  select:not(:-internal-list-box):not([multiple]) option {
-    /* min-size rules ensure that we meet accessibility guidelines for minimum target size.
-     * https://github.com/openui/open-ui/issues/1026
-     * https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html */
-    /* TODO(crbug.com/1511354): This might be able to be combined with the
-     * default select option rules at some point. This should be re-evaluted
-     * before CustomizableSelect is shipped. */
-    min-inline-size: 24px;
-    /* TODO(crbug.com/409942762): Consider removing -internal-auto-base() here
-     * if underlying performance issues with lh units are fixed. */
-    min-block-size: -internal-auto-base(24px, max(24px, 1lh));
-    font-weight: -internal-auto-base(normal, inherit);
-    padding-inline: -internal-auto-base(2px, 0.5em);
-    padding-block-end: -internal-auto-base(1px, 0);
-    display: -internal-auto-base(block, flex);
-    align-items: center;
-    gap: 0.5em;
-  }
+select:not(:-internal-list-box) option {
+  /* min-size rules ensure that we meet accessibility guidelines for minimum target size.
+   * https://github.com/openui/open-ui/issues/1026
+   * https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html */
+  /* TODO(crbug.com/41483940): This might be able to be combined with the
+   * default select option rules at some point. This should be re-evaluted
+   * before CustomizableSelect is shipped. */
+  min-inline-size: 24px;
+  /* TODO(crbug.com/409942762): Consider removing -internal-auto-base() here
+   * if underlying performance issues with lh units are fixed. */
+  min-block-size: -internal-auto-base(24px, max(24px, 1lh));
+  font-weight: -internal-auto-base(normal, inherit);
+  align-items: center;
+  gap: 0.5em;
 }
-@supports blink-feature(SelectMobileDesktopParity) {
-  select:not(:-internal-list-box) option {
-    /* min-size rules ensure that we meet accessibility guidelines for minimum target size.
-     * https://github.com/openui/open-ui/issues/1026
-     * https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html */
-    /* TODO(crbug.com/41483940): This might be able to be combined with the
-     * default select option rules at some point. This should be re-evaluted
-     * before CustomizableSelect is shipped. */
-    min-inline-size: 24px;
-    /* TODO(crbug.com/409942762): Consider removing -internal-auto-base() here
-     * if underlying performance issues with lh units are fixed. */
-    min-block-size: -internal-auto-base(24px, max(24px, 1lh));
-    font-weight: -internal-auto-base(normal, inherit);
-    align-items: center;
-    gap: 0.5em;
-  }
-  select:not(:-internal-list-box):not([multiple]) option {
-    padding-inline: -internal-auto-base(2px, 0.5em);
-    padding-block-end: -internal-auto-base(1px, 0);
-    display: -internal-auto-base(block, flex);
-  }
-  /* In the multiple case, we want to use the same styles as base appearance
-   * because the picker is rendered as a popover. */
-  select:not(:-internal-list-box)[multiple] option {
-    padding-inline: 0.5em;
-    padding-block-end: 0;
-    display: flex;
-  }
+select:not(:-internal-list-box):not([multiple]) option {
+  padding-inline: -internal-auto-base(2px, 0.5em);
+  padding-block-end: -internal-auto-base(1px, 0);
+  display: -internal-auto-base(block, flex);
+}
+/* In the multiple case, we want to use the same styles as base appearance
+ * because the picker is rendered as a popover. */
+select:not(:-internal-list-box)[multiple] option {
+  padding-inline: 0.5em;
+  padding-block-end: 0;
+  display: flex;
 }
 
-@supports not blink-feature(SelectMobileDesktopParity) {
-  select:not(:-internal-list-box):not([multiple]) option:enabled:hover {
-    background-color: color-mix(in lab, currentColor 10%, transparent);
-  }
-  select:not(:-internal-list-box):not([multiple]) option:enabled:active {
-    background-color: color-mix(in lab, currentColor 20%, transparent);
-  }
-  select:not(:-internal-list-box):not([multiple]) option:disabled {
-    color: -internal-auto-base(inherit, color-mix(in lab, currentColor 50%, transparent));
-  }
+select:not(:-internal-list-box) option:enabled:hover {
+  background-color: color-mix(in lab, currentColor 10%, transparent);
 }
-@supports blink-feature(SelectMobileDesktopParity) {
-  select:not(:-internal-list-box) option:enabled:hover {
-    background-color: color-mix(in lab, currentColor 10%, transparent);
-  }
-  select:not(:-internal-list-box) option:enabled:active {
-    background-color: color-mix(in lab, currentColor 20%, transparent);
-  }
-  select:not(:-internal-list-box) option:disabled {
-    color: -internal-auto-base(inherit, color-mix(in lab, currentColor 50%, transparent));
-  }
-  select:not(:-internal-list-box)[multiple] option:disabled {
-  /* This rule applies appearance:base styles to the appearance:auto
-   * <select multiple size=1>. Without it, disabled options would not appear disabled. */
-    color: color-mix(in lab, currentColor 50%, transparent);
-  }
+select:not(:-internal-list-box) option:enabled:active {
+  background-color: color-mix(in lab, currentColor 20%, transparent);
+}
+select:not(:-internal-list-box) option:disabled {
+  color: -internal-auto-base(inherit, color-mix(in lab, currentColor 50%, transparent));
+}
+select:not(:-internal-list-box)[multiple] option:disabled {
+/* This rule applies appearance:base styles to the appearance:auto
+ * <select multiple size=1>. Without it, disabled options would not appear disabled. */
+  color: color-mix(in lab, currentColor 50%, transparent);
 }
 @supports blink-feature(CustomizableSelectListbox) {
   /* :-internal-list-box is needed here in order to get precedence over this
@@ -2156,36 +2042,27 @@
   }
 }
 
-@supports blink-feature(SelectMobileDesktopParity) {
-  /* The svg data urls in the below ::checkmark rules are built to match the
-   * checkbox rendering in NativeThemeBase. */
-  select[multiple] option::checkmark {
-    /* The svg is 13px by 13px. Without this height rule, the svg would not be
-     * vertically centered within the ::checkmark. */
-    height: -internal-auto-base(13px, initial);
-    content: -internal-auto-base(url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2213%22%20height%3D%2213%22%20viewBox%3D%220%200%2013%2013%22%20fill%3D%22none%22%3E%3Crect%20x%3D%220.5%22%20y%3D%220.5%22%20width%3D%2212%22%20height%3D%2212%22%20rx%3D%222%22%20fill%3D%22%23ffffff%22%20stroke%3D%22%23767676%22%20stroke-width%3D%221%22%2F%3E%3C%2Fsvg%3E), '\2713');
-  }
-  select[multiple] option:checked::checkmark {
-    content: -internal-auto-base(url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2213%22%20height%3D%2213%22%20viewBox%3D%220%200%2013%2013%22%20fill%3D%22none%22%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%2213%22%20height%3D%2213%22%20rx%3D%222%22%20fill%3D%22%230075FF%22%2F%3E%3Cpath%20d%3D%22M2.6%207%20l2.6%202.5%20L10.4%202.6%22%20stroke%3D%22%23ffffff%22%20stroke-width%3D%222%22%2F%3E%3C%2Fsvg%3E), '\2713');
-  }
-  select[multiple] option:disabled::checkmark {
-    content: -internal-auto-base(url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2213%22%20height%3D%2213%22%20viewBox%3D%220%200%2013%2013%22%20fill%3D%22none%22%3E%3Crect%20x%3D%220.5%22%20y%3D%220.5%22%20width%3D%2212%22%20height%3D%2212%22%20rx%3D%222%22%20fill%3D%22%23ffffff%22%20stroke%3D%22%23767676%22%20stroke-opacity%3D%2260%25%22%20fill-opacity%3D%2260%25%22%20stroke-width%3D%221%22%2F%3E%3C%2Fsvg%3E), '\2713');
-  }
-  select[multiple] option:checked:disabled::checkmark {
-    content: -internal-auto-base(url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2213%22%20height%3D%2213%22%20viewBox%3D%220%200%2013%2013%22%20fill%3D%22none%22%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%2213%22%20height%3D%2213%22%20rx%3D%222%22%20fill%3D%22%23767676%22%20fill-opacity%3D%2260%25%22%2F%3E%3Cpath%20d%3D%22M2.6%207%20l2.6%202.5%20L10.4%202.6%22%20stroke%3D%22%23ffffff%22%20stroke-opacity%3D%2260%25%22%20stroke-width%3D%222%22%2F%3E%3C%2Fsvg%3E), '\2713');
-  }
+/* The svg data urls in the below ::checkmark rules are built to match the
+ * checkbox rendering in NativeThemeBase. */
+select[multiple] option::checkmark {
+  /* The svg is 13px by 13px. Without this height rule, the svg would not be
+   * vertically centered within the ::checkmark. */
+  height: -internal-auto-base(13px, initial);
+  content: -internal-auto-base(url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2213%22%20height%3D%2213%22%20viewBox%3D%220%200%2013%2013%22%20fill%3D%22none%22%3E%3Crect%20x%3D%220.5%22%20y%3D%220.5%22%20width%3D%2212%22%20height%3D%2212%22%20rx%3D%222%22%20fill%3D%22%23ffffff%22%20stroke%3D%22%23767676%22%20stroke-width%3D%221%22%2F%3E%3C%2Fsvg%3E), '\2713');
+}
+select[multiple] option:checked::checkmark {
+  content: -internal-auto-base(url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2213%22%20height%3D%2213%22%20viewBox%3D%220%200%2013%2013%22%20fill%3D%22none%22%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%2213%22%20height%3D%2213%22%20rx%3D%222%22%20fill%3D%22%230075FF%22%2F%3E%3Cpath%20d%3D%22M2.6%207%20l2.6%202.5%20L10.4%202.6%22%20stroke%3D%22%23ffffff%22%20stroke-width%3D%222%22%2F%3E%3C%2Fsvg%3E), '\2713');
+}
+select[multiple] option:disabled::checkmark {
+  content: -internal-auto-base(url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2213%22%20height%3D%2213%22%20viewBox%3D%220%200%2013%2013%22%20fill%3D%22none%22%3E%3Crect%20x%3D%220.5%22%20y%3D%220.5%22%20width%3D%2212%22%20height%3D%2212%22%20rx%3D%222%22%20fill%3D%22%23ffffff%22%20stroke%3D%22%23767676%22%20stroke-opacity%3D%2260%25%22%20fill-opacity%3D%2260%25%22%20stroke-width%3D%221%22%2F%3E%3C%2Fsvg%3E), '\2713');
+}
+select[multiple] option:checked:disabled::checkmark {
+  content: -internal-auto-base(url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2213%22%20height%3D%2213%22%20viewBox%3D%220%200%2013%2013%22%20fill%3D%22none%22%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%2213%22%20height%3D%2213%22%20rx%3D%222%22%20fill%3D%22%23767676%22%20fill-opacity%3D%2260%25%22%2F%3E%3Cpath%20d%3D%22M2.6%207%20l2.6%202.5%20L10.4%202.6%22%20stroke%3D%22%23ffffff%22%20stroke-opacity%3D%2260%25%22%20stroke-width%3D%222%22%2F%3E%3C%2Fsvg%3E), '\2713');
 }
 
-@supports blink-feature(SelectMobileDesktopParity) {
-  select option:not(:checked)::checkmark {
-    /* appearance:auto renders an unchecked box instead of empty space. */
-    visibility: -internal-auto-base(visible, hidden);
-  }
-}
-@supports not blink-feature(SelectMobileDesktopParity) {
-  select option:not(:checked)::checkmark {
-    visibility: hidden;
-  }
+select option:not(:checked)::checkmark {
+  /* appearance:auto renders an unchecked box instead of empty space. */
+  visibility: -internal-auto-base(visible, hidden);
 }
 
 select:-internal-autofill-selected,
@@ -2267,19 +2144,18 @@
     font-weight: normal;
   }
 }
-@supports blink-feature(SelectMobileDesktopParity) {
-  /* This rule applies appearance:base styles to the appearance:auto
-   * <select multiple size=1> optgroups. Without it, the padding would look too
-   * small. */
-  select:not(:-internal-list-box)[multiple] optgroup::-internal-optgroup-label,
-  select:not(:-internal-list-box)[multiple] optgroup legend {
-    padding-inline: 0.5em;
-    padding-block: 0;
-  }
-  select:not(:-internal-list-box)[multiple] optgroup option {
-    padding-inline-start: -internal-auto-base(1em, 0.5em);
-    font-weight: normal;
-  }
+
+/* This rule applies appearance:base styles to the appearance:auto
+ * <select multiple size=1> optgroups. Without it, the padding would look too
+ * small. */
+select:not(:-internal-list-box)[multiple] optgroup::-internal-optgroup-label,
+select:not(:-internal-list-box)[multiple] optgroup legend {
+  padding-inline: 0.5em;
+  padding-block: 0;
+}
+select:not(:-internal-list-box)[multiple] optgroup option {
+  padding-inline-start: -internal-auto-base(1em, 0.5em);
+  font-weight: normal;
 }
 
 /* These style rules control whether the select's MenuListInnerElement or
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc
index 9f09058..6b3fcc4 100644
--- a/third_party/blink/renderer/core/input/event_handler.cc
+++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -46,6 +46,7 @@
 #include "third_party/blink/renderer/core/css/style_engine.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
+#include "third_party/blink/renderer/core/dom/pseudo_element.h"
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
@@ -391,7 +392,7 @@
   const HitTestRequest& request = result.GetHitTestRequest();
   if (!request.ReadOnly()) {
     frame_->GetDocument()->UpdateHoverActiveState(
-        request.Active(), !request.Move(), result.InnerElement());
+        request.Active(), !request.Move(), result.InnerPossiblyPseudoElement());
   }
 }
 
@@ -960,14 +961,14 @@
   }
 
   mouse_event_manager_->SetClickCount(mouse_event.click_count);
-  mouse_event_manager_->SetMouseDownElement(mev.InnerElement());
+  mouse_event_manager_->SetMouseDownElement(mev.InnerPossiblyPseudoElement());
 
   if (!mouse_event.FromTouch())
     frame_->Selection().SetCaretBlinkingSuspended(true);
 
   WebInputEventResult event_result = DispatchMousePointerEvent(
-      WebInputEvent::Type::kPointerDown, mev.InnerElement(), mev.Event(),
-      Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
+      WebInputEvent::Type::kPointerDown, mev.InnerPossiblyPseudoElement(),
+      mev.Event(), Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
 
   // Disabled form controls still need to resize the scrollable area.
   if ((event_result == WebInputEventResult::kNotHandled ||
@@ -1214,7 +1215,8 @@
   if (current_subframe) {
     // Update over/out state before passing the event to the subframe.
     pointer_event_manager_->SendMouseAndPointerBoundaryEvents(
-        EffectiveMouseEventTargetElement(mev.InnerElement()), mev.Event());
+        EffectiveMouseEventTargetElement(mev.InnerPossiblyPseudoElement()),
+        mev.Event());
 
     // Event dispatch in sendMouseAndPointerBoundaryEvents may have caused the
     // subframe of the target node to be detached from its LocalFrameView, in
@@ -1253,9 +1255,9 @@
     return event_result;
   }
 
-  event_result = DispatchMousePointerEvent(WebInputEvent::Type::kPointerMove,
-                                           mev.InnerElement(), mev.Event(),
-                                           coalesced_events, predicted_events);
+  event_result = DispatchMousePointerEvent(
+      WebInputEvent::Type::kPointerMove, mev.InnerPossiblyPseudoElement(),
+      mev.Event(), coalesced_events, predicted_events);
   // Since there is no default action for the mousemove event, MouseEventManager
   // handles drag for text selection even when js cancels the mouse move event.
   // https://w3c.github.io/uievents/#event-type-mousemove
@@ -1338,8 +1340,8 @@
     event_result = WebInputEventResult::kHandledSuppressed;
   } else {
     event_result = DispatchMousePointerEvent(
-        WebInputEvent::Type::kPointerUp, mev.InnerElement(), mev.Event(),
-        Vector<WebMouseEvent>(), Vector<WebMouseEvent>(),
+        WebInputEvent::Type::kPointerUp, mev.InnerPossiblyPseudoElement(),
+        mev.Event(), Vector<WebMouseEvent>(), Vector<WebMouseEvent>(),
         (GetSelectionController().HasExtendedSelection() &&
          IsSelectionOverLink(mev)));
   }
@@ -1396,6 +1398,15 @@
   // mouseover/out dispatch)
   Element* new_target = mev.InnerElement();
 
+  // Pseudo-elements without activation behavior (::before, ::after, ::marker)
+  // are visual decorations; for drag targeting resolve them to their
+  // ultimate originating element so that drag events reach the actual content
+  // element.
+  if (auto* pseudo = DynamicTo<PseudoElement>(new_target);
+      pseudo && !pseudo->HasActivationBehavior()) {
+    new_target = &pseudo->UltimateOriginatingElement();
+  }
+
   // The drag target could be something inside a UA shadow root, in which case
   // it should be retargeted to the shadow host.
   ShadowRoot* containing_root =
@@ -2054,8 +2065,8 @@
   HitTestRequest request(hit_type | HitTestRequest::kAllowChildFrameContent);
   if (!request.ReadOnly()) {
     UpdateCrossFrameHoverActiveState(
-        request.Active(),
-        event_with_hit_test_results.GetHitTestResult().InnerElement());
+        request.Active(), event_with_hit_test_results.GetHitTestResult()
+                              .InnerPossiblyPseudoElement());
   }
 
   if (should_keep_active_for_min_interval) {
@@ -2200,8 +2211,9 @@
   // |SelectionController::sendContextMenuEvent()|.
   document.UpdateStyleAndLayout(DocumentUpdateReason::kContextMenu);
 
-  Element* target_element =
-      override_target_element ? override_target_element : mev.InnerElement();
+  Element* target_element = override_target_element
+                                ? override_target_element
+                                : mev.InnerPossiblyPseudoElement();
   WebInputEventResult result =
       mouse_event_manager_
           ->DispatchMouseEvent(
@@ -2423,7 +2435,8 @@
       HitTestResult result(request, location);
       layout_object->HitTest(location, result);
       frame_->GetDocument()->UpdateHoverActiveState(
-          request.Active(), !request.Move(), result.InnerElement());
+          request.Active(), !request.Move(),
+          result.InnerPossiblyPseudoElement());
     }
   }
 }
@@ -2650,7 +2663,8 @@
 
       if (!request.ReadOnly()) {
         frame_->GetDocument()->UpdateHoverActiveState(
-            request.Active(), !request.Move(), result.InnerElement());
+            request.Active(), !request.Move(),
+            result.InnerPossiblyPseudoElement());
       }
 
       return MouseEventWithHitTestResults(
diff --git a/third_party/blink/renderer/core/input/gesture_manager.cc b/third_party/blink/renderer/core/input/gesture_manager.cc
index 2f36af5..66e5fdb2 100644
--- a/third_party/blink/renderer/core/input/gesture_manager.cc
+++ b/third_party/blink/renderer/core/input/gesture_manager.cc
@@ -256,8 +256,8 @@
     // should actually suppress RecomputeMouseHoverState until the user moves
     // the mouse or navigates away.
     mouse_event_manager_->SetElementUnderMouseAndDispatchMouseEvent(
-        current_hit_test.InnerElement(), event_type_names::kMousemove,
-        fake_mouse_move);
+        current_hit_test.InnerPossiblyPseudoElement(),
+        event_type_names::kMousemove, fake_mouse_move);
   }
 
   // Do a new hit-test in case the mousemove event changed the DOM.
@@ -283,7 +283,7 @@
   gfx::Point tapped_position =
       gfx::ToFlooredPoint(gesture_event.PositionInRootFrame());
   Node* tapped_node = current_hit_test.InnerNode();
-  Element* tapped_element = current_hit_test.InnerElement();
+  Element* tapped_element = current_hit_test.InnerPossiblyPseudoElement();
   LocalFrame::NotifyUserActivation(
       tapped_node ? tapped_node->GetDocument().GetFrame() : nullptr,
       mojom::blink::UserActivationNotificationType::kInteraction);
@@ -308,8 +308,8 @@
 
     mouse_down_event_result =
         mouse_event_manager_->SetElementUnderMouseAndDispatchMouseEvent(
-            current_hit_test.InnerElement(), event_type_names::kMousedown,
-            fake_mouse_down);
+            current_hit_test.InnerPossiblyPseudoElement(),
+            event_type_names::kMousedown, fake_mouse_down);
     selection_controller_->InitializeSelectionState();
     if (mouse_down_event_result == WebInputEventResult::kNotHandled) {
       mouse_down_event_result = mouse_event_manager_->HandleMouseFocus(
@@ -353,13 +353,16 @@
       suppress_mouse_events_from_gestures_
           ? WebInputEventResult::kHandledSuppressed
           : mouse_event_manager_->SetElementUnderMouseAndDispatchMouseEvent(
-                current_hit_test.InnerElement(), event_type_names::kMouseup,
-                fake_mouse_up);
+                current_hit_test.InnerPossiblyPseudoElement(),
+                event_type_names::kMouseup, fake_mouse_up);
 
   WebInputEventResult click_event_result = WebInputEventResult::kNotHandled;
   if (tapped_element) {
     if (current_hit_test.InnerNode()) {
-      Node* click_target_node = current_hit_test.InnerNode()->CommonAncestor(
+      Node* inner_up_node = current_hit_test.InnerPossiblyPseudoNode()
+                                ? current_hit_test.InnerPossiblyPseudoNode()
+                                : current_hit_test.InnerNode();
+      Node* click_target_node = inner_up_node->CommonAncestor(
           *tapped_element, event_handling_util::ParentForClickEvent);
       auto* click_target_element = DynamicTo<Element>(click_target_node);
       PointerId pointer_id = GetPointerIdFromWebGestureEvent(gesture_event);
diff --git a/third_party/blink/renderer/core/input/mouse_event_manager.h b/third_party/blink/renderer/core/input/mouse_event_manager.h
index 292163e..4b8c66fb 100644
--- a/third_party/blink/renderer/core/input/mouse_event_manager.h
+++ b/third_party/blink/renderer/core/input/mouse_event_manager.h
@@ -246,8 +246,8 @@
   unsigned svg_pan_ : 1;
   unsigned mouse_down_may_start_drag_ : 1;
 
-  // Tracks the element that received the last mousedown event.  This is cleared
-  // on mouseup.
+  // Tracks the element that received the last mousedown event. For
+  // hit-testable pseudos, this is the pseudo itself. Cleared on mouseup.
   Member<Element> mousedown_element_;
   Member<Node> mouse_press_node_;
 
diff --git a/third_party/blink/renderer/core/layout/grid/grid_item.cc b/third_party/blink/renderer/core/layout/grid/grid_item.cc
index 02a5a07..4e86aa2e 100644
--- a/third_party/blink/renderer/core/layout/grid/grid_item.cc
+++ b/third_party/blink/renderer/core/layout/grid/grid_item.cc
@@ -183,9 +183,14 @@
   // context as specified in:
   //   https://drafts.csswg.org/css-contain-2/#containment-layout
   //   https://drafts.csswg.org/css-contain-2/#containment-paint
+  //
+  // TODO(almaher): Check for grid-lanes here, as well, once we add support
+  // for grid-lanes subgridded to another grid* container.
   if (node.IsGrid() && !node.ShouldApplyLayoutContainment() &&
       !node.ShouldApplyPaintContainment() &&
       !style.IsContainerForSizeContainerQueries()) {
+    // TODO(almaher): If the parent grid is a grid-lanes container, then we only
+    // consider subgrids in the grid axis.
     has_subgridded_columns =
         is_parallel_with_root_grid
             ? style.GridTemplateColumns().IsSubgriddedAxis()
diff --git a/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.cc
index d05a584..9a623249 100644
--- a/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.cc
@@ -290,8 +290,8 @@
 
   // If we have inline size containment ignore all children.
   auto grid_sizing_tree = node.ShouldApplyInlineSizeContainment()
-                              ? BuildGridSizingTreeIgnoringChildren()
-                              : BuildGridSizingTree();
+                              ? BuildGridSizingTreeIgnoringChildren(*this)
+                              : BuildGridSizingTree(*this);
 
   bool depends_on_block_constraints = false;
   auto ComputeTotalColumnSize =
@@ -343,247 +343,6 @@
                                      SizingConstraint::kMaxContent);
 }
 
-namespace {
-
-GridArea SubgriddedAreaInParent(const SubgriddedItemData& opt_subgrid_data) {
-  if (!opt_subgrid_data.IsSubgrid()) {
-    return GridArea();
-  }
-
-  auto subgridded_area_in_parent = opt_subgrid_data->resolved_position;
-
-  if (!opt_subgrid_data->has_subgridded_columns) {
-    subgridded_area_in_parent.columns = GridSpan::IndefiniteGridSpan();
-  }
-  if (!opt_subgrid_data->has_subgridded_rows) {
-    subgridded_area_in_parent.rows = GridSpan::IndefiniteGridSpan();
-  }
-
-  if (!opt_subgrid_data->is_parallel_with_root_grid) {
-    std::swap(subgridded_area_in_parent.columns,
-              subgridded_area_in_parent.rows);
-  }
-  return subgridded_area_in_parent;
-}
-
-FragmentGeometry CalculateInitialFragmentGeometryForSubgrid(
-    const GridItemData& subgrid_data,
-    const ConstraintSpace& space,
-    const GridSizingSubtree& sizing_subtree = kNoGridSizingSubtree) {
-  DCHECK(subgrid_data.IsSubgrid());
-
-  const auto& node = To<GridNode>(subgrid_data.node);
-  {
-    const bool subgrid_has_standalone_columns =
-        subgrid_data.is_parallel_with_root_grid
-            ? !subgrid_data.has_subgridded_columns
-            : !subgrid_data.has_subgridded_rows;
-
-    // We won't be able to resolve the intrinsic sizes of a subgrid if its
-    // tracks are subgridded, i.e., their sizes can't be resolved by the subgrid
-    // itself, or if `sizing_subtree` is not provided, i.e., the grid sizing
-    // tree it's not completed at this step of the sizing algorithm.
-    if (subgrid_has_standalone_columns && sizing_subtree) {
-      return CalculateInitialFragmentGeometry(
-          space, node, /* break_token */ nullptr,
-          [&](SizeType) -> MinMaxSizesResult {
-            return node.ComputeSubgridMinMaxSizes(sizing_subtree, space);
-          });
-    }
-  }
-
-  bool needs_to_compute_min_max_sizes = false;
-
-  const auto fragment_geometry = CalculateInitialFragmentGeometry(
-      space, node, /* break_token */ nullptr,
-      [&needs_to_compute_min_max_sizes](SizeType) -> MinMaxSizesResult {
-        // We can't call `ComputeMinMaxSizes` for a subgrid with an incomplete
-        // grid sizing tree, as its intrinsic size relies on its subtree. If we
-        // end up in this function, we need to use an intrinsic fragment
-        // geometry instead to avoid a cyclic dependency.
-        needs_to_compute_min_max_sizes = true;
-        return MinMaxSizesResult();
-      });
-
-  if (needs_to_compute_min_max_sizes) {
-    return CalculateInitialFragmentGeometry(space, node,
-                                            /* break_token */ nullptr,
-                                            /* is_intrinsic */ true);
-  }
-  return fragment_geometry;
-}
-
-}  // namespace
-
-void GridLayoutAlgorithm::BuildGridSizingSubtree(
-    GridSizingTree* sizing_tree,
-    HeapVector<Member<LayoutBox>>* opt_oof_children,
-    const SubgriddedItemData& opt_subgrid_data,
-    const GridLineResolver* opt_parent_line_resolver,
-    bool must_invalidate_placement_cache,
-    bool must_ignore_children) const {
-  DCHECK(sizing_tree);
-
-  const auto& node = Node();
-  const auto& style = node.Style();
-
-  sizing_tree->AddToPreorderTraversal(node);
-
-  const auto subgrid_area = SubgriddedAreaInParent(opt_subgrid_data);
-  const auto column_auto_repetitions =
-      ComputeAutomaticRepetitions(subgrid_area.columns, kForColumns);
-  const auto row_auto_repetitions =
-      ComputeAutomaticRepetitions(subgrid_area.rows, kForRows);
-  const auto writing_mode = GetConstraintSpace().GetWritingMode();
-
-  // Initialize this grid's line resolver.
-  const auto line_resolver =
-      opt_parent_line_resolver
-          ? GridLineResolver(style, *opt_parent_line_resolver, subgrid_area,
-                             column_auto_repetitions, row_auto_repetitions)
-          : GridLineResolver(style, column_auto_repetitions,
-                             row_auto_repetitions);
-
-  GridItems grid_items;
-  GridLayoutData layout_data;
-  bool has_nested_subgrid = false;
-  wtf_size_t column_start_offset = 0;
-  wtf_size_t row_start_offset = 0;
-
-  if (!must_ignore_children) {
-    // Construct grid items that are not subgridded.
-    grid_items =
-        node.ConstructGridItems(line_resolver, &must_invalidate_placement_cache,
-                                opt_oof_children, &has_nested_subgrid);
-
-    const auto& placement_data = node.CachedPlacementData();
-    column_start_offset = placement_data.column_start_offset;
-    row_start_offset = placement_data.row_start_offset;
-  }
-
-  auto BuildSizingCollection = [&](GridTrackSizingDirection track_direction) {
-    GridRangeBuilder range_builder(
-        style, track_direction, line_resolver.AutoRepetitions(track_direction),
-        (track_direction == kForColumns) ? column_start_offset
-                                         : row_start_offset);
-
-    bool must_create_baselines = false;
-    for (auto& grid_item : grid_items.IncludeSubgriddedItems()) {
-      if (grid_item.IsConsideredForSizing(track_direction)) {
-        must_create_baselines |= grid_item.IsBaselineSpecified(track_direction);
-      }
-
-      if (grid_item.MustCachePlacementIndices(track_direction)) {
-        auto& range_indices = grid_item.RangeIndices(track_direction);
-        range_builder.EnsureTrackCoverage(grid_item.StartLine(track_direction),
-                                          grid_item.SpanSize(track_direction),
-                                          &range_indices.begin,
-                                          &range_indices.end);
-      }
-    }
-
-    layout_data.SetTrackCollection(std::make_unique<GridSizingTrackCollection>(
-        range_builder.FinalizeRanges(), track_direction,
-        must_create_baselines));
-  };
-
-  const bool has_standalone_columns = subgrid_area.columns.IsIndefinite();
-  const bool has_standalone_rows = subgrid_area.rows.IsIndefinite();
-
-  if (has_standalone_columns) {
-    BuildSizingCollection(kForColumns);
-  }
-  if (has_standalone_rows) {
-    BuildSizingCollection(kForRows);
-  }
-
-  if (!has_nested_subgrid) {
-    sizing_tree->SetSizingNodeData(node, std::move(grid_items),
-                                   std::move(layout_data));
-    return;
-  }
-
-  InitializeTrackCollection(opt_subgrid_data, kForColumns, &layout_data);
-  InitializeTrackCollection(opt_subgrid_data, kForRows, &layout_data);
-
-  if (has_standalone_columns) {
-    layout_data.SizingCollection(kForColumns).CacheDefiniteSetsGeometry();
-  }
-  if (has_standalone_rows) {
-    layout_data.SizingCollection(kForRows).CacheDefiniteSetsGeometry();
-  }
-
-  // `AppendSubgriddedItems` rely on the cached placement data of a subgrid to
-  // construct its grid items, so we need to build their subtrees beforehand.
-  for (auto& grid_item : grid_items) {
-    if (!grid_item.IsSubgrid()) {
-      continue;
-    }
-
-    // TODO(ethavar): Currently we have an issue where we can't correctly cache
-    // the set indices of this grid item to determine its available space. This
-    // happens because subgridded items are not considered by the range builder
-    // since they can't be placed before we recurse into subgrids.
-    grid_item.ComputeSetIndices(layout_data.Columns());
-    grid_item.ComputeSetIndices(layout_data.Rows());
-
-    const auto space = CreateConstraintSpaceForLayout(grid_item, layout_data);
-    const auto fragment_geometry =
-        CalculateInitialFragmentGeometryForSubgrid(grid_item, space);
-
-    const GridLayoutAlgorithm subgrid_algorithm(
-        {grid_item.node, fragment_geometry, space});
-
-    subgrid_algorithm.BuildGridSizingSubtree(
-        sizing_tree, /*opt_oof_children=*/nullptr,
-        SubgriddedItemData(grid_item, layout_data, writing_mode),
-        &line_resolver, must_invalidate_placement_cache);
-
-    // After we accommodate subgridded items in their respective sizing track
-    // collections, their placement indices might be incorrect, so we want to
-    // recompute them when we call `InitializeTrackSizes`.
-    grid_item.ResetPlacementIndices();
-  }
-
-  node.AppendSubgriddedItems(&grid_items);
-
-  // We need to recreate the track builder collections to ensure track coverage
-  // for subgridded items; it would be ideal to have them accounted for already,
-  // but we might need the track collections to compute a subgrid's automatic
-  // repetitions, so we do this process twice to avoid a cyclic dependency.
-  if (has_standalone_columns) {
-    BuildSizingCollection(kForColumns);
-  }
-  if (has_standalone_rows) {
-    BuildSizingCollection(kForRows);
-  }
-
-  sizing_tree->SetSizingNodeData(node, std::move(grid_items),
-                                 std::move(layout_data));
-}
-
-GridSizingTree GridLayoutAlgorithm::BuildGridSizingTree(
-    HeapVector<Member<LayoutBox>>* opt_oof_children) const {
-  DCHECK(!GetConstraintSpace().GetGridLayoutSubtree());
-
-  GridSizingTree sizing_tree;
-  BuildGridSizingSubtree(&sizing_tree, opt_oof_children);
-  return sizing_tree;
-}
-
-GridSizingTree GridLayoutAlgorithm::BuildGridSizingTreeIgnoringChildren()
-    const {
-  DCHECK(!GetConstraintSpace().GetGridLayoutSubtree());
-
-  GridSizingTree sizing_tree;
-  BuildGridSizingSubtree(&sizing_tree, /*opt_oof_children=*/nullptr,
-                         /*opt_subgrid_data=*/kNoSubgriddedItemData,
-                         /*opt_parent_line_resolver=*/nullptr,
-                         /*must_invalidate_placement_cache=*/false,
-                         /*must_ignore_children=*/true);
-  return sizing_tree;
-}
-
 GridLayoutSubtree GridLayoutAlgorithm::ComputeGridGeometry(
     GridItems* grid_items,
     LayoutUnit* intrinsic_block_size,
@@ -649,8 +408,8 @@
   }
 
   auto grid_sizing_tree = node.ChildLayoutBlockedByDisplayLock()
-                              ? BuildGridSizingTreeIgnoringChildren()
-                              : BuildGridSizingTree(oof_children);
+                              ? BuildGridSizingTreeIgnoringChildren(*this)
+                              : BuildGridSizingTree(*this, oof_children);
 
   InitializeTrackSizes(&grid_sizing_tree);
 
@@ -753,7 +512,7 @@
   if (override_intrinsic_block_size != kIndefiniteSize)
     return BorderScrollbarPadding().BlockSum() + override_intrinsic_block_size;
 
-  auto grid_sizing_tree = BuildGridSizingTreeIgnoringChildren();
+  auto grid_sizing_tree = BuildGridSizingTreeIgnoringChildren(*this);
 
   InitializeTrackSizes(&grid_sizing_tree, kForRows);
   CompleteTrackSizingAlgorithm(kForRows, SizingConstraint::kLayout,
@@ -1247,54 +1006,6 @@
   }
 }
 
-std::unique_ptr<GridLayoutTrackCollection>
-GridLayoutAlgorithm::CreateSubgridTrackCollection(
-    const SubgriddedItemData& subgrid_data,
-    GridTrackSizingDirection track_direction) const {
-  DCHECK(subgrid_data.IsSubgrid());
-
-  const bool is_for_columns_in_parent = subgrid_data->is_parallel_with_root_grid
-                                            ? track_direction == kForColumns
-                                            : track_direction == kForRows;
-
-  const auto& style = Style();
-  const auto& parent_track_collection =
-      is_for_columns_in_parent ? subgrid_data.Columns() : subgrid_data.Rows();
-  const auto& range_indices = is_for_columns_in_parent
-                                  ? subgrid_data->column_range_indices
-                                  : subgrid_data->row_range_indices;
-
-  return std::make_unique<GridLayoutTrackCollection>(
-      parent_track_collection.CreateSubgridTrackCollection(
-          range_indices.begin, range_indices.end,
-          GridTrackSizingAlgorithm::CalculateGutterSize(
-              style, grid_available_size_, track_direction,
-              parent_track_collection.GutterSize()),
-          ComputeMarginsForSelf(GetConstraintSpace(), style),
-          BorderScrollbarPadding(), track_direction,
-          is_for_columns_in_parent
-              ? subgrid_data->is_opposite_direction_in_root_grid_columns
-              : subgrid_data->is_opposite_direction_in_root_grid_rows));
-}
-
-void GridLayoutAlgorithm::InitializeTrackCollection(
-    const SubgriddedItemData& opt_subgrid_data,
-    GridTrackSizingDirection track_direction,
-    GridLayoutData* layout_data) const {
-  if (layout_data->HasSubgriddedAxis(track_direction)) {
-    // If we don't have a sizing collection for this axis, then we're in a
-    // subgrid that must inherit the track collection of its parent grid.
-    DCHECK(opt_subgrid_data.IsSubgrid());
-
-    layout_data->SetTrackCollection(
-        CreateSubgridTrackCollection(opt_subgrid_data, track_direction));
-    return;
-  }
-
-  auto& track_collection = layout_data->SizingCollection(track_direction);
-  track_collection.BuildSets(Style(), grid_available_size_);
-}
-
 namespace {
 
 GridTrackSizingDirection RelativeDirectionInSubgrid(
@@ -1328,9 +1039,13 @@
 
   auto& grid_items = sizing_subtree.GetGridItems();
   auto& layout_data = sizing_subtree.LayoutData();
+  const ComputedStyle& style = Style();
+  const BoxStrut& border_scrollbar_padding = BorderScrollbarPadding();
 
   auto InitAndCacheTrackSizes = [&](GridTrackSizingDirection track_direction) {
-    InitializeTrackCollection(opt_subgrid_data, track_direction, &layout_data);
+    InitializeTrackCollection(opt_subgrid_data, style, GetConstraintSpace(),
+                              border_scrollbar_padding, GetGridAvailableSize(),
+                              track_direction, &layout_data);
 
     if (layout_data.HasSubgriddedAxis(track_direction)) {
       const auto& track_collection = (track_direction == kForColumns)
@@ -1349,16 +1064,16 @@
       if (!track_collection.HasNonDefiniteTrack()) {
         auto first_set_geometry =
             GridTrackSizingAlgorithm::ComputeFirstSetGeometry(
-                track_collection, Style(), grid_available_size_,
-                BorderScrollbarPadding());
+                track_collection, style, grid_available_size_,
+                border_scrollbar_padding);
 
         track_collection.FinalizeSetsGeometry(first_set_geometry.start_offset,
                                               first_set_geometry.gutter_size);
       } else {
         track_collection.CacheInitializedSetsGeometry(
             (track_direction == kForColumns)
-                ? BorderScrollbarPadding().inline_start
-                : BorderScrollbarPadding().block_start);
+                ? border_scrollbar_padding.inline_start
+                : border_scrollbar_padding.block_start);
       }
 
       if (track_collection.HasBaselines()) {
@@ -1375,7 +1090,7 @@
   }
 
   ForEachSubgrid(
-      sizing_subtree,
+      sizing_subtree, *this,
       [&](const GridLayoutAlgorithm& subgrid_algorithm,
           const GridSizingSubtree& subgrid_subtree,
           const SubgriddedItemData& subgrid_data) {
@@ -1525,6 +1240,8 @@
   DCHECK(sizing_subtree.HasValidRootFor(Node()));
 
   auto& layout_data = sizing_subtree.LayoutData();
+  const ComputedStyle& style = Style();
+  const BoxStrut& border_scrollbar_padding = BorderScrollbarPadding();
 
   const bool is_for_columns = track_direction == kForColumns;
   const bool has_non_definite_track =
@@ -1537,8 +1254,9 @@
       // subgrid that must inherit the track collection of its parent grid.
       DCHECK(opt_subgrid_data.IsSubgrid());
 
-      layout_data.SetTrackCollection(
-          CreateSubgridTrackCollection(opt_subgrid_data, track_direction));
+      layout_data.SetTrackCollection(CreateSubgridTrackCollection(
+          opt_subgrid_data, style, GetConstraintSpace(),
+          border_scrollbar_padding, GetGridAvailableSize(), track_direction));
     } else {
       ComputeUsedTrackSizes(sizing_subtree, track_direction, sizing_constraint);
 
@@ -1559,8 +1277,8 @@
 
       auto first_set_geometry =
           GridTrackSizingAlgorithm::ComputeFirstSetGeometry(
-              track_collection, Style(), grid_available_size_,
-              BorderScrollbarPadding());
+              track_collection, style, grid_available_size_,
+              border_scrollbar_padding);
 
       track_collection.FinalizeSetsGeometry(first_set_geometry.start_offset,
                                             first_set_geometry.gutter_size);
@@ -1574,9 +1292,10 @@
   }
 
   ForEachSubgrid(
-      sizing_subtree, [&](const GridLayoutAlgorithm& subgrid_algorithm,
-                          const GridSizingSubtree& subgrid_subtree,
-                          const SubgriddedItemData& subgrid_data) {
+      sizing_subtree, *this,
+      [&](const GridLayoutAlgorithm& subgrid_algorithm,
+          const GridSizingSubtree& subgrid_subtree,
+          const SubgriddedItemData& subgrid_data) {
         subgrid_algorithm.CompleteTrackSizingAlgorithm(
             subgrid_subtree, subgrid_data,
             RelativeDirectionInSubgrid(track_direction, *subgrid_data),
@@ -1682,7 +1401,9 @@
                                                     : opt_subgrid_data.Rows();
           if (parent_track_collection.HasBaselines()) {
             layout_data.SetTrackCollection(CreateSubgridTrackCollection(
-                opt_subgrid_data, track_direction));
+                opt_subgrid_data, Style(), GetConstraintSpace(),
+                BorderScrollbarPadding(), GetGridAvailableSize(),
+                track_direction));
           }
         } else {
           ComputeGridItemBaselines(layout_tree, sizing_subtree, track_direction,
@@ -1697,7 +1418,7 @@
     ComputeOrRecreateBaselines(kForRows);
   }
 
-  ForEachSubgrid(sizing_subtree,
+  ForEachSubgrid(sizing_subtree, *this,
                  [&](const GridLayoutAlgorithm& subgrid_algorithm,
                      const GridSizingSubtree& subgrid_subtree,
                      const SubgriddedItemData& subgrid_data) {
@@ -1717,42 +1438,6 @@
       /*opt_track_direction=*/std::nullopt, SizingConstraint::kLayout);
 }
 
-template <typename CallbackFunc>
-void GridLayoutAlgorithm::ForEachSubgrid(
-    const GridSizingSubtree& sizing_subtree,
-    const CallbackFunc& callback_func,
-    bool should_compute_min_max_sizes) const {
-  // Exit early if this subtree doesn't have nested subgrids.
-  auto next_subgrid_subtree = sizing_subtree.FirstChild();
-  if (!next_subgrid_subtree) {
-    return;
-  }
-
-  const auto& layout_data = sizing_subtree.LayoutData();
-
-  for (const auto& grid_item : sizing_subtree.GetGridItems()) {
-    if (!grid_item.IsSubgrid()) {
-      continue;
-    }
-
-    const auto space = CreateConstraintSpaceForLayout(grid_item, layout_data);
-    const auto fragment_geometry = CalculateInitialFragmentGeometryForSubgrid(
-        grid_item, space,
-        should_compute_min_max_sizes ? next_subgrid_subtree
-                                     : kNoGridSizingSubtree);
-
-    const GridLayoutAlgorithm subgrid_algorithm(
-        {grid_item.node, fragment_geometry, space});
-
-    DCHECK(next_subgrid_subtree);
-    callback_func(subgrid_algorithm, next_subgrid_subtree,
-                  SubgriddedItemData(grid_item, layout_data,
-                                     GetConstraintSpace().GetWritingMode()));
-
-    next_subgrid_subtree = next_subgrid_subtree.NextSibling();
-  }
-}
-
 LayoutUnit GridLayoutAlgorithm::ComputeSubgridIntrinsicSize(
     const GridSizingSubtree& sizing_subtree,
     GridTrackSizingDirection track_direction,
diff --git a/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.h b/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.h
index d4f6a91..35d8edf 100644
--- a/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.h
@@ -25,6 +25,12 @@
  public:
   explicit GridLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
+  // Expose base class accessors needed by functions in grid_layout_utils.
+  using LayoutAlgorithm::BorderScrollbarPadding;
+  using LayoutAlgorithm::GetConstraintSpace;
+  using LayoutAlgorithm::Node;
+  using LayoutAlgorithm::Style;
+
   const LayoutResult* Layout();
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&);
 
@@ -43,23 +49,26 @@
       const LogicalSize& border_box_size,
       GridItemData* out_of_flow_item);
 
+  wtf_size_t ComputeAutomaticRepetitions(
+      const GridSpan& subgrid_span,
+      GridTrackSizingDirection track_direction) const;
+
+  // `containing_grid_area` is an optional out parameter that holds the computed
+  // grid area (offset and size) of the specified grid item.
+  ConstraintSpace CreateConstraintSpaceForLayout(
+      const GridItemData& grid_item,
+      const GridLayoutData& layout_data,
+      GridLayoutSubtree&& opt_layout_subtree = GridLayoutSubtree(),
+      LogicalRect* containing_grid_area = nullptr,
+      LayoutUnit unavailable_block_size = LayoutUnit(),
+      bool min_block_size_should_encompass_intrinsic_size = false,
+      std::optional<LayoutUnit> opt_child_block_offset = std::nullopt) const;
+
+  LogicalSize GetGridAvailableSize() const { return grid_available_size_; }
+
  private:
   friend class GridLayoutAlgorithmTest;
 
-  // Aggregate all direct out of flow children from the current grid container
-  // to `opt_oof_children`, unless it's not provided.
-  void BuildGridSizingSubtree(
-      GridSizingTree* sizing_tree,
-      HeapVector<Member<LayoutBox>>* opt_oof_children,
-      const SubgriddedItemData& opt_subgrid_data = kNoSubgriddedItemData,
-      const GridLineResolver* opt_parent_line_resolver = nullptr,
-      bool must_invalidate_placement_cache = false,
-      bool must_ignore_children = false) const;
-
-  GridSizingTree BuildGridSizingTree(
-      HeapVector<Member<LayoutBox>>* opt_oof_children = nullptr) const;
-  GridSizingTree BuildGridSizingTreeIgnoringChildren() const;
-
   const LayoutResult* LayoutInternal();
 
   GridLayoutSubtree ComputeGridGeometry(
@@ -78,10 +87,6 @@
       SizingConstraint sizing_constraint,
       GridItemData* grid_item) const;
 
-  wtf_size_t ComputeAutomaticRepetitions(
-      const GridSpan& subgrid_span,
-      GridTrackSizingDirection track_direction) const;
-
   // Subgrids compute auto repetitions differently than standalone grids.
   wtf_size_t ComputeAutomaticRepetitionsForSubgrid(
       wtf_size_t subgrid_span_size,
@@ -94,15 +99,6 @@
                                 GridTrackSizingDirection track_direction,
                                 SizingConstraint sizing_constraint) const;
 
-  std::unique_ptr<GridLayoutTrackCollection> CreateSubgridTrackCollection(
-      const SubgriddedItemData& subgrid_data,
-      GridTrackSizingDirection track_direction) const;
-
-  // Initialize the track collections of a given grid sizing data.
-  void InitializeTrackCollection(const SubgriddedItemData& opt_subgrid_data,
-                                 GridTrackSizingDirection track_direction,
-                                 GridLayoutData* layout_data) const;
-
   // Initializes the track sizes of a grid sizing subtree.
   void InitializeTrackSizes(
       const GridSizingSubtree& sizing_subtree,
@@ -145,13 +141,6 @@
   // Helper that calls the method above for the entire grid sizing tree.
   void CompleteFinalBaselineAlignment(GridSizingTree* sizing_tree) const;
 
-  // Helper which iterates over the sizing tree, and instantiates a subgrid
-  // algorithm to invoke the callback with.
-  template <typename CallbackFunc>
-  void ForEachSubgrid(const GridSizingSubtree& sizing_subtree,
-                      const CallbackFunc& callback_func,
-                      bool should_compute_min_max_sizes = true) const;
-
   LayoutUnit ComputeSubgridIntrinsicSize(
       const GridSizingSubtree& sizing_subtree,
       GridTrackSizingDirection track_direction,
@@ -166,17 +155,6 @@
       bool min_block_size_should_encompass_intrinsic_size = false,
       std::optional<LayoutUnit> opt_child_block_offset = std::nullopt) const;
 
-  // `containing_grid_area` is an optional out parameter that holds the computed
-  // grid area (offset and size) of the specified grid item.
-  ConstraintSpace CreateConstraintSpaceForLayout(
-      const GridItemData& grid_item,
-      const GridLayoutData& layout_data,
-      GridLayoutSubtree&& opt_layout_subtree = GridLayoutSubtree(),
-      LogicalRect* containing_grid_area = nullptr,
-      LayoutUnit unavailable_block_size = LayoutUnit(),
-      bool min_block_size_should_encompass_intrinsic_size = false,
-      std::optional<LayoutUnit> opt_child_block_offset = std::nullopt) const;
-
   ConstraintSpace CreateConstraintSpaceForMeasure(
       const SubgriddedItemData& subgridded_item,
       GridTrackSizingDirection track_direction,
diff --git a/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm_test.cc
index 7be31c2..8e72a56 100644
--- a/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm_test.cc
@@ -6,6 +6,7 @@
 
 #include "build/build_config.h"
 #include "third_party/blink/renderer/core/layout/base_layout_algorithm_test.h"
+#include "third_party/blink/renderer/core/layout/grid/grid_layout_utils.h"
 #include "third_party/blink/renderer/core/layout/grid/grid_track_sizing_algorithm.h"
 #include "third_party/blink/renderer/core/layout/length_utils.h"
 #include "third_party/blink/renderer/core/layout/physical_box_fragment.h"
@@ -33,7 +34,7 @@
   void SetUp() override { BaseLayoutAlgorithmTest::SetUp(); }
 
   void BuildGridGeometry(const GridLayoutAlgorithm& algorithm) {
-    auto grid_sizing_tree = algorithm.BuildGridSizingTree();
+    auto grid_sizing_tree = BuildGridSizingTree(algorithm);
 
     algorithm.InitializeTrackSizes(&grid_sizing_tree);
     algorithm.CompleteTrackSizingAlgorithm(
diff --git a/third_party/blink/renderer/core/layout/grid/grid_layout_utils.cc b/third_party/blink/renderer/core/layout/grid/grid_layout_utils.cc
index c832cbff..041ae2d0 100644
--- a/third_party/blink/renderer/core/layout/grid/grid_layout_utils.cc
+++ b/third_party/blink/renderer/core/layout/grid/grid_layout_utils.cc
@@ -11,7 +11,9 @@
 #include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
 #include "third_party/blink/renderer/core/layout/geometry/static_position.h"
 #include "third_party/blink/renderer/core/layout/grid/grid_item.h"
+#include "third_party/blink/renderer/core/layout/grid/grid_line_resolver.h"
 #include "third_party/blink/renderer/core/layout/grid/grid_track_collection.h"
+#include "third_party/blink/renderer/core/layout/grid/grid_track_sizing_algorithm.h"
 #include "third_party/blink/renderer/core/layout/length_utils.h"
 #include "third_party/blink/renderer/core/layout/logical_box_fragment.h"
 #include "third_party/blink/renderer/core/style/grid_track_list.h"
@@ -637,4 +639,309 @@
   return std::min(min_content_contribution, spanned_tracks_definite_max_size);
 }
 
+namespace {
+
+GridArea SubgriddedAreaInParent(const SubgriddedItemData& opt_subgrid_data) {
+  if (!opt_subgrid_data.IsSubgrid()) {
+    return GridArea();
+  }
+
+  auto subgridded_area_in_parent = opt_subgrid_data->resolved_position;
+
+  if (!opt_subgrid_data->has_subgridded_columns) {
+    subgridded_area_in_parent.columns = GridSpan::IndefiniteGridSpan();
+  }
+  if (!opt_subgrid_data->has_subgridded_rows) {
+    subgridded_area_in_parent.rows = GridSpan::IndefiniteGridSpan();
+  }
+
+  if (!opt_subgrid_data->is_parallel_with_root_grid) {
+    std::swap(subgridded_area_in_parent.columns,
+              subgridded_area_in_parent.rows);
+  }
+  return subgridded_area_in_parent;
+}
+
+}  // namespace
+
+void BuildGridSizingSubtree(const GridLayoutAlgorithm& algorithm,
+                            GridSizingTree* sizing_tree,
+                            HeapVector<Member<LayoutBox>>* opt_oof_children,
+                            const SubgriddedItemData& opt_subgrid_data,
+                            const GridLineResolver* opt_parent_line_resolver,
+                            bool must_invalidate_placement_cache,
+                            bool must_ignore_children) {
+  DCHECK(sizing_tree);
+
+  const auto& node = algorithm.Node();
+  const auto& style = node.Style();
+
+  sizing_tree->AddToPreorderTraversal(node);
+
+  const auto subgrid_area = SubgriddedAreaInParent(opt_subgrid_data);
+  const auto column_auto_repetitions =
+      algorithm.ComputeAutomaticRepetitions(subgrid_area.columns, kForColumns);
+  const auto row_auto_repetitions =
+      algorithm.ComputeAutomaticRepetitions(subgrid_area.rows, kForRows);
+  const auto constraint_space = algorithm.GetConstraintSpace();
+  const auto writing_mode = constraint_space.GetWritingMode();
+
+  // Initialize this grid's line resolver.
+  const auto line_resolver =
+      opt_parent_line_resolver
+          ? GridLineResolver(style, *opt_parent_line_resolver, subgrid_area,
+                             column_auto_repetitions, row_auto_repetitions)
+          : GridLineResolver(style, column_auto_repetitions,
+                             row_auto_repetitions);
+
+  GridItems grid_items;
+  GridLayoutData layout_data;
+  bool has_nested_subgrid = false;
+  wtf_size_t column_start_offset = 0;
+  wtf_size_t row_start_offset = 0;
+
+  if (!must_ignore_children) {
+    // Construct grid items that are not subgridded.
+    grid_items =
+        node.ConstructGridItems(line_resolver, &must_invalidate_placement_cache,
+                                opt_oof_children, &has_nested_subgrid);
+
+    const auto& placement_data = node.CachedPlacementData();
+    column_start_offset = placement_data.column_start_offset;
+    row_start_offset = placement_data.row_start_offset;
+  }
+
+  auto BuildSizingCollection = [&](GridTrackSizingDirection track_direction) {
+    GridRangeBuilder range_builder(
+        style, track_direction, line_resolver.AutoRepetitions(track_direction),
+        (track_direction == kForColumns) ? column_start_offset
+                                         : row_start_offset);
+
+    bool must_create_baselines = false;
+    for (auto& grid_item : grid_items.IncludeSubgriddedItems()) {
+      if (grid_item.IsConsideredForSizing(track_direction)) {
+        must_create_baselines |= grid_item.IsBaselineSpecified(track_direction);
+      }
+
+      if (grid_item.MustCachePlacementIndices(track_direction)) {
+        auto& range_indices = grid_item.RangeIndices(track_direction);
+        range_builder.EnsureTrackCoverage(grid_item.StartLine(track_direction),
+                                          grid_item.SpanSize(track_direction),
+                                          &range_indices.begin,
+                                          &range_indices.end);
+      }
+    }
+
+    layout_data.SetTrackCollection(std::make_unique<GridSizingTrackCollection>(
+        range_builder.FinalizeRanges(), track_direction,
+        must_create_baselines));
+  };
+
+  const bool has_standalone_columns = subgrid_area.columns.IsIndefinite();
+  const bool has_standalone_rows = subgrid_area.rows.IsIndefinite();
+
+  if (has_standalone_columns) {
+    BuildSizingCollection(kForColumns);
+  }
+  if (has_standalone_rows) {
+    BuildSizingCollection(kForRows);
+  }
+
+  if (!has_nested_subgrid) {
+    sizing_tree->SetSizingNodeData(node, std::move(grid_items),
+                                   std::move(layout_data));
+    return;
+  }
+
+  InitializeTrackCollection(opt_subgrid_data, style, constraint_space,
+                            algorithm.BorderScrollbarPadding(),
+                            algorithm.GetGridAvailableSize(), kForColumns,
+                            &layout_data);
+  InitializeTrackCollection(opt_subgrid_data, style, constraint_space,
+                            algorithm.BorderScrollbarPadding(),
+                            algorithm.GetGridAvailableSize(), kForRows,
+                            &layout_data);
+
+  if (has_standalone_columns) {
+    layout_data.SizingCollection(kForColumns).CacheDefiniteSetsGeometry();
+  }
+  if (has_standalone_rows) {
+    layout_data.SizingCollection(kForRows).CacheDefiniteSetsGeometry();
+  }
+
+  // `AppendSubgriddedItems` rely on the cached placement data of a subgrid to
+  // construct its grid items, so we need to build their subtrees beforehand.
+  for (auto& grid_item : grid_items) {
+    if (!grid_item.IsSubgrid()) {
+      continue;
+    }
+
+    // TODO(ethavar): Currently we have an issue where we can't correctly cache
+    // the set indices of this grid item to determine its available space. This
+    // happens because subgridded items are not considered by the range builder
+    // since they can't be placed before we recurse into subgrids.
+    grid_item.ComputeSetIndices(layout_data.Columns());
+    grid_item.ComputeSetIndices(layout_data.Rows());
+
+    const auto space =
+        algorithm.CreateConstraintSpaceForLayout(grid_item, layout_data);
+    const auto fragment_geometry =
+        CalculateInitialFragmentGeometryForSubgrid(grid_item, space);
+
+    // TODO(almaher): Use the grid lanes algorithm if the subgrid requires it.
+    const GridLayoutAlgorithm subgrid_algorithm(
+        {grid_item.node, fragment_geometry, space});
+
+    BuildGridSizingSubtree(
+        subgrid_algorithm, sizing_tree, /*opt_oof_children=*/nullptr,
+        SubgriddedItemData(grid_item, layout_data, writing_mode),
+        &line_resolver, must_invalidate_placement_cache);
+
+    // After we accommodate subgridded items in their respective sizing track
+    // collections, their placement indices might be incorrect, so we want to
+    // recompute them when we call `InitializeTrackSizes`.
+    grid_item.ResetPlacementIndices();
+  }
+
+  node.AppendSubgriddedItems(&grid_items);
+
+  // We need to recreate the track builder collections to ensure track coverage
+  // for subgridded items; it would be ideal to have them accounted for already,
+  // but we might need the track collections to compute a subgrid's automatic
+  // repetitions, so we do this process twice to avoid a cyclic dependency.
+  if (has_standalone_columns) {
+    BuildSizingCollection(kForColumns);
+  }
+  if (has_standalone_rows) {
+    BuildSizingCollection(kForRows);
+  }
+
+  sizing_tree->SetSizingNodeData(node, std::move(grid_items),
+                                 std::move(layout_data));
+}
+
+GridSizingTree BuildGridSizingTree(
+    const GridLayoutAlgorithm& algorithm,
+    HeapVector<Member<LayoutBox>>* opt_oof_children) {
+  DCHECK(!algorithm.GetConstraintSpace().GetGridLayoutSubtree());
+
+  GridSizingTree sizing_tree;
+  BuildGridSizingSubtree(algorithm, &sizing_tree, opt_oof_children);
+  return sizing_tree;
+}
+
+GridSizingTree BuildGridSizingTreeIgnoringChildren(
+    const GridLayoutAlgorithm& algorithm) {
+  DCHECK(!algorithm.GetConstraintSpace().GetGridLayoutSubtree());
+
+  GridSizingTree sizing_tree;
+  BuildGridSizingSubtree(algorithm, &sizing_tree, /*opt_oof_children=*/nullptr,
+                         /*opt_subgrid_data=*/kNoSubgriddedItemData,
+                         /*opt_parent_line_resolver=*/nullptr,
+                         /*must_invalidate_placement_cache=*/false,
+                         /*must_ignore_children=*/true);
+  return sizing_tree;
+}
+
+FragmentGeometry CalculateInitialFragmentGeometryForSubgrid(
+    const GridItemData& subgrid_data,
+    const ConstraintSpace& space,
+    const GridSizingSubtree& sizing_subtree) {
+  DCHECK(subgrid_data.IsSubgrid());
+
+  const auto& node = To<GridNode>(subgrid_data.node);
+  {
+    const bool subgrid_has_standalone_columns =
+        subgrid_data.is_parallel_with_root_grid
+            ? !subgrid_data.has_subgridded_columns
+            : !subgrid_data.has_subgridded_rows;
+
+    // We won't be able to resolve the intrinsic sizes of a subgrid if its
+    // tracks are subgridded, i.e., their sizes can't be resolved by the subgrid
+    // itself, or if `sizing_subtree` is not provided, i.e., the grid sizing
+    // tree it's not completed at this step of the sizing algorithm.
+    if (subgrid_has_standalone_columns && sizing_subtree) {
+      return CalculateInitialFragmentGeometry(
+          space, node, /* break_token */ nullptr,
+          [&](SizeType) -> MinMaxSizesResult {
+            return node.ComputeSubgridMinMaxSizes(sizing_subtree, space);
+          });
+    }
+  }
+
+  bool needs_to_compute_min_max_sizes = false;
+
+  const auto fragment_geometry = CalculateInitialFragmentGeometry(
+      space, node, /* break_token */ nullptr,
+      [&needs_to_compute_min_max_sizes](SizeType) -> MinMaxSizesResult {
+        // We can't call `ComputeMinMaxSizes` for a subgrid with an incomplete
+        // grid sizing tree, as its intrinsic size relies on its subtree. If we
+        // end up in this function, we need to use an intrinsic fragment
+        // geometry instead to avoid a cyclic dependency.
+        needs_to_compute_min_max_sizes = true;
+        return MinMaxSizesResult();
+      });
+
+  if (needs_to_compute_min_max_sizes) {
+    return CalculateInitialFragmentGeometry(space, node,
+                                            /* break_token */ nullptr,
+                                            /* is_intrinsic */ true);
+  }
+  return fragment_geometry;
+}
+
+std::unique_ptr<GridLayoutTrackCollection> CreateSubgridTrackCollection(
+    const SubgriddedItemData& subgrid_data,
+    const ComputedStyle& style,
+    const ConstraintSpace& space,
+    const BoxStrut& border_scrollbar_padding,
+    const LogicalSize grid_available_size,
+    GridTrackSizingDirection track_direction) {
+  DCHECK(subgrid_data.IsSubgrid());
+
+  const bool is_for_columns_in_parent = subgrid_data->is_parallel_with_root_grid
+                                            ? track_direction == kForColumns
+                                            : track_direction == kForRows;
+
+  const auto& parent_track_collection =
+      is_for_columns_in_parent ? subgrid_data.Columns() : subgrid_data.Rows();
+  const auto& range_indices = is_for_columns_in_parent
+                                  ? subgrid_data->column_range_indices
+                                  : subgrid_data->row_range_indices;
+
+  return std::make_unique<GridLayoutTrackCollection>(
+      parent_track_collection.CreateSubgridTrackCollection(
+          range_indices.begin, range_indices.end,
+          GridTrackSizingAlgorithm::CalculateGutterSize(
+              style, grid_available_size, track_direction,
+              parent_track_collection.GutterSize()),
+          ComputeMarginsForSelf(space, style), border_scrollbar_padding,
+          track_direction,
+          is_for_columns_in_parent
+              ? subgrid_data->is_opposite_direction_in_root_grid_columns
+              : subgrid_data->is_opposite_direction_in_root_grid_rows));
+}
+
+void InitializeTrackCollection(const SubgriddedItemData& opt_subgrid_data,
+                               const ComputedStyle& style,
+                               const ConstraintSpace& space,
+                               const BoxStrut& border_scrollbar_padding,
+                               const LogicalSize grid_available_size,
+                               GridTrackSizingDirection track_direction,
+                               GridLayoutData* layout_data) {
+  if (layout_data->HasSubgriddedAxis(track_direction)) {
+    // If we don't have a sizing collection for this axis, then we're in a
+    // subgrid that must inherit the track collection of its parent grid.
+    DCHECK(opt_subgrid_data.IsSubgrid());
+
+    layout_data->SetTrackCollection(CreateSubgridTrackCollection(
+        opt_subgrid_data, style, space, border_scrollbar_padding,
+        grid_available_size, track_direction));
+    return;
+  }
+
+  auto& track_collection = layout_data->SizingCollection(track_direction);
+  track_collection.BuildSets(style, grid_available_size);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/grid/grid_layout_utils.h b/third_party/blink/renderer/core/layout/grid/grid_layout_utils.h
index e09b843..b1bfda3 100644
--- a/third_party/blink/renderer/core/layout/grid/grid_layout_utils.h
+++ b/third_party/blink/renderer/core/layout/grid/grid_layout_utils.h
@@ -5,6 +5,8 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GRID_GRID_LAYOUT_UTILS_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GRID_GRID_LAYOUT_UTILS_H_
 
+#include "third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.h"
+#include "third_party/blink/renderer/core/layout/grid/grid_sizing_tree.h"
 #include "third_party/blink/renderer/core/style/grid_enums.h"
 #include "third_party/blink/renderer/core/style/grid_track_size.h"
 #include "third_party/blink/renderer/platform/fonts/font_baseline.h"
@@ -17,13 +19,17 @@
 class BlockNode;
 class BoxFragmentBuilder;
 class ConstraintSpace;
+class GridLayoutData;
 class GridLayoutTrackCollection;
+class GridLineResolver;
 class GridSizingTrackCollection;
 class GridTrackList;
+class LayoutBox;
 class LogicalBoxFragment;
 
 enum class AxisEdge;
 struct BoxStrut;
+struct FragmentGeometry;
 struct GridItemData;
 struct LogicalSize;
 struct LogicalStaticPosition;
@@ -165,6 +171,89 @@
     GridTrackSizingDirection track_direction,
     LayoutUnit available_size);
 
+// Aggregate all direct out of flow children from the grid container associated
+// with `algorithm` to `opt_oof_children`, unless it's not provided.
+//
+// TODO(almaher): Make these methods take a template type for the layout
+// algorithm to allow this to work with grid-lanes, as well.
+void BuildGridSizingSubtree(
+    const GridLayoutAlgorithm& algorithm,
+    GridSizingTree* sizing_tree,
+    HeapVector<Member<LayoutBox>>* opt_oof_children,
+    const SubgriddedItemData& opt_subgrid_data = kNoSubgriddedItemData,
+    const GridLineResolver* opt_parent_line_resolver = nullptr,
+    bool must_invalidate_placement_cache = false,
+    bool must_ignore_children = false);
+
+CORE_EXPORT GridSizingTree
+BuildGridSizingTree(const GridLayoutAlgorithm& algorithm,
+                    HeapVector<Member<LayoutBox>>* opt_oof_children = nullptr);
+GridSizingTree BuildGridSizingTreeIgnoringChildren(
+    const GridLayoutAlgorithm& algorithm);
+
+// Calculate the initial fragment geometry for a subgrid item.
+FragmentGeometry CalculateInitialFragmentGeometryForSubgrid(
+    const GridItemData& subgrid_data,
+    const ConstraintSpace& space,
+    const GridSizingSubtree& sizing_subtree = kNoGridSizingSubtree);
+
+// Helper which iterates over the sizing tree, and instantiates a subgrid
+// algorithm to invoke the callback with.
+template <typename CallbackFunc>
+void ForEachSubgrid(const GridSizingSubtree& sizing_subtree,
+                    const GridLayoutAlgorithm& algorithm,
+                    const CallbackFunc& callback_func,
+                    bool should_compute_min_max_sizes = true) {
+  // Exit early if this subtree doesn't have nested subgrids.
+  auto next_subgrid_subtree = sizing_subtree.FirstChild();
+  if (!next_subgrid_subtree) {
+    return;
+  }
+
+  const auto& layout_data = sizing_subtree.LayoutData();
+
+  for (const auto& grid_item : sizing_subtree.GetGridItems()) {
+    if (!grid_item.IsSubgrid()) {
+      continue;
+    }
+
+    const auto space =
+        algorithm.CreateConstraintSpaceForLayout(grid_item, layout_data);
+    const auto fragment_geometry = CalculateInitialFragmentGeometryForSubgrid(
+        grid_item, space,
+        should_compute_min_max_sizes ? next_subgrid_subtree
+                                     : kNoGridSizingSubtree);
+
+    const GridLayoutAlgorithm subgrid_algorithm(
+        {grid_item.node, fragment_geometry, space});
+
+    DCHECK(next_subgrid_subtree);
+    callback_func(
+        subgrid_algorithm, next_subgrid_subtree,
+        SubgriddedItemData(grid_item, layout_data,
+                           algorithm.GetConstraintSpace().GetWritingMode()));
+
+    next_subgrid_subtree = next_subgrid_subtree.NextSibling();
+  }
+}
+
+std::unique_ptr<GridLayoutTrackCollection> CreateSubgridTrackCollection(
+    const SubgriddedItemData& subgrid_data,
+    const ComputedStyle& style,
+    const ConstraintSpace& space,
+    const BoxStrut& border_scrollbar_padding,
+    const LogicalSize grid_available_size,
+    GridTrackSizingDirection track_direction);
+
+// Initialize the track collections of a given grid sizing data.
+void InitializeTrackCollection(const SubgriddedItemData& opt_subgrid_data,
+                               const ComputedStyle& style,
+                               const ConstraintSpace& space,
+                               const BoxStrut& border_scrollbar_padding,
+                               const LogicalSize grid_available_size,
+                               GridTrackSizingDirection track_direction,
+                               GridLayoutData* layout_data);
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GRID_GRID_LAYOUT_UTILS_H_
diff --git a/third_party/blink/renderer/core/layout/hit_test_result.cc b/third_party/blink/renderer/core/layout/hit_test_result.cc
index b0d280c..4979fd1 100644
--- a/third_party/blink/renderer/core/layout/hit_test_result.cc
+++ b/third_party/blink/renderer/core/layout/hit_test_result.cc
@@ -328,6 +328,13 @@
   }
 
   inner_possibly_pseudo_node_ = n;
+  // InnerNodeForHitTesting() always resolves to the originating DOM element for
+  // any pseudo-element (including activation-behavior pseudos like
+  // ::scroll-marker). inner_node_ is therefore always a non-pseudo Element,
+  // which is required for editing/selection (IsEditable, CanStartSelection,
+  // GetPosition).
+  // The raw pseudo is kept in inner_possibly_pseudo_node_ and exposed via
+  // InnerPossiblyPseudoElement() for hover/active state and event dispatch.
   if (auto* pseudo_element = DynamicTo<PseudoElement>(n))
     n = pseudo_element->InnerNodeForHitTesting();
   inner_node_ = n;
@@ -341,6 +348,15 @@
     inner_element_ = FlatTreeTraversal::ParentElement(*inner_node_);
 }
 
+Element* HitTestResult::InnerPossiblyPseudoElement() const {
+  if (auto* pseudo =
+          DynamicTo<PseudoElement>(inner_possibly_pseudo_node_.Get());
+      pseudo && pseudo->SupportsHitTesting()) {
+    return pseudo;
+  }
+  return inner_element_.Get();
+}
+
 void HitTestResult::SetURLElement(Element* n) {
   inner_url_element_ = n;
 }
diff --git a/third_party/blink/renderer/core/layout/hit_test_result.h b/third_party/blink/renderer/core/layout/hit_test_result.h
index 9babbff..622cd1c 100644
--- a/third_party/blink/renderer/core/layout/hit_test_result.h
+++ b/third_party/blink/renderer/core/layout/hit_test_result.h
@@ -89,6 +89,11 @@
   }
   CompositorElementId GetScrollableContainer() const;
   Element* InnerElement() const { return inner_element_.Get(); }
+  // Returns the hit-testable pseudo-element (::scroll-marker, ::scroll-button,
+  // ::interest-hint, etc.) if one was hit, otherwise falls back to
+  // InnerElement(). Use this for hover/active state updates and event dispatch
+  // so that activation-behavior pseudos receive events correctly.
+  Element* InnerPossiblyPseudoElement() const;
 
   // If innerNode is an image map or image map area, return the associated image
   // node.
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc b/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc
index 08ac657..0eceeec 100644
--- a/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc
@@ -1490,11 +1490,6 @@
 }
 
 TEST_P(LayoutBoxModelObjectTest, UpdateStackingContextForOption) {
-  // We do not create LayoutObject for option elements inside multiple selects
-  // on platforms where DelegatesMenuListRendering() returns true like Android.
-  if (LayoutTheme::GetTheme().DelegatesMenuListRendering())
-    return;
-
   SetBodyInnerHTML(R"HTML(
     <style>
       @keyframes op {
diff --git a/third_party/blink/renderer/core/layout/layout_box_test.cc b/third_party/blink/renderer/core/layout/layout_box_test.cc
index 148918e..d456ece3 100644
--- a/third_party/blink/renderer/core/layout/layout_box_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_box_test.cc
@@ -1818,6 +1818,8 @@
     }
     #target {
       position: absolute;
+      position-anchor: --a;
+      inset: auto;
     }
   )CSS");
   SetBodyInnerHTML(R"HTML(
@@ -1825,7 +1827,7 @@
       <div id="cb">
         <div id="spacer"></div>
         <div id="anchor"></div>
-        <div id="target" anchor="anchor"></div>
+        <div id="target"></div>
       </div>
     </div>
   )HTML");
@@ -1834,8 +1836,6 @@
   EXPECT_EQ(GetLayoutObjectByElementId("anchor"),
             target->FindTargetAnchor(*MakeGarbageCollected<ScopedCSSName>(
                 AtomicString("--a"), &GetDocument())));
-  EXPECT_EQ(GetLayoutObjectByElementId("anchor"),
-            target->AcceptableImplicitAnchor());
 }
 
 TEST_F(LayoutBoxTest, AnchorInInlineContainingBlock) {
@@ -1844,8 +1844,8 @@
       <span id="not-implicit-anchor">not implicit anchor</span>
       <span style="position: relative">
         <span id="anchor" style="anchor-name: --a">anchor</span>
-        <div id="target" anchor="not-implicit-anchor"
-             style="position: absolute; top: anchor(--a top)"></div>
+        <div id="target"
+             style="position-anchor: --a; position: absolute; top: anchor(--a top)"></div>
       </span>
       some text
     </div>
diff --git a/third_party/blink/renderer/core/layout/layout_theme.cc b/third_party/blink/renderer/core/layout/layout_theme.cc
index 4fac259..f46ed98 100644
--- a/third_party/blink/renderer/core/layout/layout_theme.cc
+++ b/third_party/blink/renderer/core/layout/layout_theme.cc
@@ -877,14 +877,6 @@
                                       : GetTheme().PlatformFocusRingColor();
 }
 
-bool LayoutTheme::DelegatesMenuListRendering() const {
-  return delegates_menu_list_rendering_;
-}
-
-void LayoutTheme::SetDelegatesMenuListRenderingForTesting(bool flag) {
-  delegates_menu_list_rendering_ = flag;
-}
-
 String LayoutTheme::DisplayNameForFile(const File& file) const {
   return file.name();
 }
diff --git a/third_party/blink/renderer/core/layout/layout_theme.h b/third_party/blink/renderer/core/layout/layout_theme.h
index f264eaa..01b81c5 100644
--- a/third_party/blink/renderer/core/layout/layout_theme.h
+++ b/third_party/blink/renderer/core/layout/layout_theme.h
@@ -176,11 +176,6 @@
   // Returns the distance of slider tick origin from the slider track center.
   virtual int SliderTickOffsetFromTrackCenter() const = 0;
 
-  // Functions for <select> elements.
-  virtual bool DelegatesMenuListRendering() const;
-  // This function has no effect for LayoutThemeAndroid, of which
-  // DelegatesMenuListRendering() always returns true.
-  void SetDelegatesMenuListRenderingForTesting(bool flag);
   virtual bool PopsMenuByArrowKeys() const { return false; }
   virtual bool PopsMenuByReturnKey() const { return true; }
 
@@ -277,8 +272,6 @@
   bool has_custom_focus_ring_color_;
   base::TimeDelta caret_blink_interval_ = base::Milliseconds(500);
 
-  bool delegates_menu_list_rendering_ = false;
-
   // This color is expected to be drawn on a semi-transparent overlay,
   // making it more transparent than its alpha value indicates.
   static constexpr Color kDefaultTapHighlightColor =
diff --git a/third_party/blink/renderer/core/layout/layout_theme_android.h b/third_party/blink/renderer/core/layout/layout_theme_android.h
index f147ac5..6f79bce0 100644
--- a/third_party/blink/renderer/core/layout/layout_theme_android.h
+++ b/third_party/blink/renderer/core/layout/layout_theme_android.h
@@ -16,7 +16,6 @@
                     mojom::blink::ColorScheme color_scheme,
                     const ui::ColorProvider* color_provider,
                     bool is_in_web_app_scope) const override;
-  bool DelegatesMenuListRendering() const override { return true; }
   Color PlatformActiveSelectionBackgroundColor(
       mojom::blink::ColorScheme color_scheme) const override;
   Color PlatformActiveSelectionForegroundColor(
diff --git a/third_party/blink/renderer/core/layout/layout_theme_ios.h b/third_party/blink/renderer/core/layout/layout_theme_ios.h
index 67b84dc..61f5f957 100644
--- a/third_party/blink/renderer/core/layout/layout_theme_ios.h
+++ b/third_party/blink/renderer/core/layout/layout_theme_ios.h
@@ -12,7 +12,6 @@
 class LayoutThemeIOS final : public LayoutThemeMobile {
  public:
   static scoped_refptr<LayoutTheme> Create();
-  bool DelegatesMenuListRendering() const override { return true; }
   Color PlatformActiveSelectionBackgroundColor(
       mojom::blink::ColorScheme color_scheme) const override;
   Color PlatformActiveSelectionForegroundColor(
diff --git a/third_party/blink/renderer/core/navigation_api/build.gni b/third_party/blink/renderer/core/navigation_api/build.gni
index a538f8c0..941501e2a 100644
--- a/third_party/blink/renderer/core/navigation_api/build.gni
+++ b/third_party/blink/renderer/core/navigation_api/build.gni
@@ -20,6 +20,7 @@
   "navigation_precommit_controller.h",
   "navigation_transition.cc",
   "navigation_transition.h",
+  "navigation_type_util.h",
 ]
 
 blink_core_tests_navigation_api = [ "navigation_api_test.cc" ]
diff --git a/third_party/blink/renderer/core/navigation_api/navigate_event.cc b/third_party/blink/renderer/core/navigation_api/navigate_event.cc
index bc884bbe..612816f9 100644
--- a/third_party/blink/renderer/core/navigation_api/navigate_event.cc
+++ b/third_party/blink/renderer/core/navigation_api/navigate_event.cc
@@ -42,6 +42,7 @@
 #include "third_party/blink/renderer/core/navigation_api/navigation_defer_page_swap_controller.h"
 #include "third_party/blink/renderer/core/navigation_api/navigation_destination.h"
 #include "third_party/blink/renderer/core/navigation_api/navigation_precommit_controller.h"
+#include "third_party/blink/renderer/core/navigation_api/navigation_type_util.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -52,21 +53,6 @@
 
 namespace blink {
 
-WebFrameLoadType LoadTypeFromNavigation(
-    V8NavigationType::Enum navigation_type) {
-  switch (navigation_type) {
-    case V8NavigationType::Enum::kPush:
-      return WebFrameLoadType::kStandard;
-    case V8NavigationType::Enum::kReplace:
-      return WebFrameLoadType::kReplaceCurrentItem;
-    case V8NavigationType::Enum::kTraverse:
-      return WebFrameLoadType::kBackForward;
-    case V8NavigationType::Enum::kReload:
-      return WebFrameLoadType::kReload;
-  }
-  NOTREACHED();
-}
-
 enum class HandlerPhase { kPrecommit, kPostcommit };
 
 class NavigateEvent::FulfillReaction final
@@ -504,7 +490,7 @@
   DomWindow()->document()->Loader()->RunURLAndHistoryUpdateSteps(
       dispatch_params_->url, dispatch_params_->destination_item,
       mojom::blink::SameDocumentNavigationType::kNavigationApiIntercept,
-      state_object, LoadTypeFromNavigation(navigation_type_), fire_popstate,
+      state_object, ToWebFrameLoadType(navigation_type_), fire_popstate,
       dispatch_params_->should_skip_screenshot,
       dispatch_params_->is_browser_initiated,
       dispatch_params_->is_synchronously_committed_same_document,
@@ -738,8 +724,8 @@
   // point. Using mojom::blink::ScrollRestorationType::kManual would block the
   // scroll.
   DomWindow()->GetFrame()->Loader().ProcessScrollForSameDocumentNavigation(
-      dispatch_params_->url, LoadTypeFromNavigation(navigation_type_),
-      view_state, mojom::blink::ScrollRestorationType::kAuto, scroll_behavior);
+      dispatch_params_->url, ToWebFrameLoadType(navigation_type_), view_state,
+      mojom::blink::ScrollRestorationType::kAuto, scroll_behavior);
 }
 
 const AtomicString& NavigateEvent::InterfaceName() const {
diff --git a/third_party/blink/renderer/core/navigation_api/navigation_api.cc b/third_party/blink/renderer/core/navigation_api/navigation_api.cc
index b265465..2bd74af 100644
--- a/third_party/blink/renderer/core/navigation_api/navigation_api.cc
+++ b/third_party/blink/renderer/core/navigation_api/navigation_api.cc
@@ -43,6 +43,7 @@
 #include "third_party/blink/renderer/core/navigation_api/navigation_destination.h"
 #include "third_party/blink/renderer/core/navigation_api/navigation_history_entry.h"
 #include "third_party/blink/renderer/core/navigation_api/navigation_transition.h"
+#include "third_party/blink/renderer/core/navigation_api/navigation_type_util.h"
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/route_matching/route_map.h"
 #include "third_party/blink/renderer/core/timing/soft_navigation_heuristics.h"
@@ -94,22 +95,6 @@
   return result;
 }
 
-V8NavigationType::Enum DetermineNavigationType(WebFrameLoadType type) {
-  switch (type) {
-    case WebFrameLoadType::kStandard:
-      return V8NavigationType::Enum::kPush;
-    case WebFrameLoadType::kBackForward:
-    case WebFrameLoadType::kRestore:
-      return V8NavigationType::Enum::kTraverse;
-    case WebFrameLoadType::kReload:
-    case WebFrameLoadType::kReloadBypassingCache:
-      return V8NavigationType::Enum::kReload;
-    case WebFrameLoadType::kReplaceCurrentItem:
-      return V8NavigationType::Enum::kReplace;
-  }
-  NOTREACHED();
-}
-
 NavigationApi::NavigationApi(LocalDOMWindow* window)
     : window_(window),
       activation_(MakeGarbageCollected<NavigationActivation>()) {}
@@ -144,7 +129,7 @@
   V8NavigationType::Enum navigation_type =
       window_->GetFrame()->GetPage()->IsPrerendering()
           ? V8NavigationType::Enum::kPush
-          : DetermineNavigationType(load_type);
+          : ToV8NavigationType(load_type);
   activation_->Update(currentEntry(), previous_history_entry, navigation_type);
 }
 
@@ -296,7 +281,7 @@
                             v8::MicrotasksScope::kRunMicrotasks);
 
   auto* init = NavigationCurrentEntryChangeEventInit::Create();
-  init->setNavigationType(DetermineNavigationType(type));
+  init->setNavigationType(ToV8NavigationType(type));
   init->setFrom(old_current);
   DispatchEvent(*NavigationCurrentEntryChangeEvent::Create(
       event_type_names::kCurrententrychange, init));
@@ -787,7 +772,7 @@
 
   auto* init = NavigateEventInit::Create();
   V8NavigationType::Enum navigation_type =
-      DetermineNavigationType(params->frame_load_type);
+      ToV8NavigationType(params->frame_load_type);
   init->setNavigationType(navigation_type);
 
   SerializedScriptValue* destination_state = nullptr;
diff --git a/third_party/blink/renderer/core/navigation_api/navigation_type_util.h b/third_party/blink/renderer/core/navigation_api/navigation_type_util.h
new file mode 100644
index 0000000..5e11741
--- /dev/null
+++ b/third_party/blink/renderer/core/navigation_api/navigation_type_util.h
@@ -0,0 +1,88 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_NAVIGATION_API_NAVIGATION_TYPE_UTIL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_NAVIGATION_API_NAVIGATION_TYPE_UTIL_H_
+
+#include "base/notreached.h"
+#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-shared.h"
+#include "third_party/blink/public/web/web_frame_load_type.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_navigation_type.h"
+
+namespace blink {
+
+// Returns the web-exposed navigation type for the given `WebFrameLoadType`,
+// converting it to the appropriate value.
+constexpr V8NavigationType::Enum ToV8NavigationType(WebFrameLoadType type) {
+  switch (type) {
+    case WebFrameLoadType::kStandard:
+      return V8NavigationType::Enum::kPush;
+    case WebFrameLoadType::kBackForward:
+    case WebFrameLoadType::kRestore:
+      return V8NavigationType::Enum::kTraverse;
+    case WebFrameLoadType::kReload:
+    case WebFrameLoadType::kReloadBypassingCache:
+      return V8NavigationType::Enum::kReload;
+    case WebFrameLoadType::kReplaceCurrentItem:
+      return V8NavigationType::Enum::kReplace;
+  }
+  NOTREACHED();
+}
+
+// Returns the `WebFrameLoadType` for the given web-exposed navigation type.
+//
+// Note: ToWebFrameLoadType(ToV8NavigationType(load_type)) will not necessarily
+// return load_type since there is not a 1:1 conversion from `WebFrameLoadType`.
+constexpr WebFrameLoadType ToWebFrameLoadType(V8NavigationType::Enum type) {
+  switch (type) {
+    case V8NavigationType::Enum::kPush:
+      return WebFrameLoadType::kStandard;
+    case V8NavigationType::Enum::kReplace:
+      return WebFrameLoadType::kReplaceCurrentItem;
+    case V8NavigationType::Enum::kTraverse:
+      return WebFrameLoadType::kBackForward;
+    case V8NavigationType::Enum::kReload:
+      return WebFrameLoadType::kReload;
+  }
+  NOTREACHED();
+}
+
+// Returns the mojom enum value for the given web-exposed enum value. The
+// conversion is 1:1.
+constexpr mojom::blink::NavigationTypeForNavigationApi
+ToNavigationTypeForNavigationApi(V8NavigationType::Enum type) {
+  switch (type) {
+    case V8NavigationType::Enum::kPush:
+      return mojom::blink::NavigationTypeForNavigationApi::kPush;
+    case V8NavigationType::Enum::kTraverse:
+      return mojom::blink::NavigationTypeForNavigationApi::kTraverse;
+    case V8NavigationType::Enum::kReload:
+      return mojom::blink::NavigationTypeForNavigationApi::kReload;
+    case V8NavigationType::Enum::kReplace:
+      return mojom::blink::NavigationTypeForNavigationApi::kReplace;
+  }
+  NOTREACHED();
+}
+
+// Returns the web-exposed navigation type for the given mojom enum value. The
+// conversion is 1:1.
+constexpr V8NavigationType::Enum ToV8NavigationType(
+    mojom::blink::NavigationTypeForNavigationApi type) {
+  switch (type) {
+    case mojom::blink::NavigationTypeForNavigationApi::kPush:
+      return V8NavigationType::Enum::kPush;
+    case mojom::blink::NavigationTypeForNavigationApi::kTraverse:
+      return V8NavigationType::Enum::kTraverse;
+    case mojom::blink::NavigationTypeForNavigationApi::kReplace:
+      return V8NavigationType::Enum::kReplace;
+    case mojom::blink::NavigationTypeForNavigationApi::kReload:
+      return V8NavigationType::Enum::kReload;
+  }
+  NOTREACHED();
+}
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_NAVIGATION_API_NAVIGATION_TYPE_UTIL_H_
diff --git a/third_party/blink/renderer/core/page/event_with_hit_test_results.h b/third_party/blink/renderer/core/page/event_with_hit_test_results.h
index 127f6a5..7c6cb731 100644
--- a/third_party/blink/renderer/core/page/event_with_hit_test_results.h
+++ b/third_party/blink/renderer/core/page/event_with_hit_test_results.h
@@ -52,6 +52,9 @@
   }
   Node* InnerNode() const { return hit_test_result_.InnerNode(); }
   Element* InnerElement() const { return hit_test_result_.InnerElement(); }
+  Element* InnerPossiblyPseudoElement() const {
+    return hit_test_result_.InnerPossiblyPseudoElement();
+  }
 
   const HitTestLocation& GetHitTestLocation() const {
     return hit_test_location_;
diff --git a/third_party/blink/renderer/core/page/focusgroup_controller.cc b/third_party/blink/renderer/core/page/focusgroup_controller.cc
index d5639573..a71a89a 100644
--- a/third_party/blink/renderer/core/page/focusgroup_controller.cc
+++ b/third_party/blink/renderer/core/page/focusgroup_controller.cc
@@ -31,10 +31,6 @@
   ExecutionContext* context = frame->DomWindow()->GetExecutionContext();
   DCHECK(RuntimeEnabledFeatures::FocusgroupEnabled(context));
 
-  FocusgroupDirection direction = utils::FocusgroupDirectionForEvent(event);
-  if (direction == FocusgroupDirection::kNone)
-    return false;
-
   if (!frame->GetDocument())
     return false;
 
@@ -46,6 +42,16 @@
     return false;
   }
 
+  // Resolve the logical direction from the focused element's writing mode.
+  // This means arrow keys follow the element's local writing direction: in an
+  // RTL context ArrowLeft is forward-inline, in vertical-rl ArrowDown is
+  // forward-inline, etc.
+  FocusgroupDirection direction =
+      utils::FocusgroupDirectionForEvent(event, *focused);
+  if (direction == FocusgroupDirection::kNone) {
+    return false;
+  }
+
   // If the currently focused element is (or is within) an arrow key handler
   // for its focusgroup owner on the navigation axis, do not run focusgroup
   // arrow navigation. The interactive control's native arrow-key behavior
diff --git a/third_party/blink/renderer/core/page/focusgroup_controller_test.cc b/third_party/blink/renderer/core/page/focusgroup_controller_test.cc
index d721a73..8c9ac91 100644
--- a/third_party/blink/renderer/core/page/focusgroup_controller_test.cc
+++ b/third_party/blink/renderer/core/page/focusgroup_controller_test.cc
@@ -280,51 +280,143 @@
 }
 
 TEST_F(FocusgroupControllerTest, FocusgroupDirectionForEventValid) {
-  // Arrow right should be forward and inline.
+  SetBodyInnerHTML(R"HTML(
+    <div id=ltr>LTR element</div>
+  )HTML");
+  UpdateAllLifecyclePhasesForTest();
+  auto* ltr_element = GetElementById("ltr");
+  ASSERT_TRUE(ltr_element);
+
+  // Arrow right should be forward and inline (in LTR horizontal-tb).
   auto* event = KeyDownEvent(ui::DomKey::ARROW_RIGHT);
-  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event),
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *ltr_element),
             FocusgroupDirection::kForwardInline);
 
   // Arrow down should be forward and block.
   event = KeyDownEvent(ui::DomKey::ARROW_DOWN);
-  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event),
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *ltr_element),
             FocusgroupDirection::kForwardBlock);
 
   // Arrow left should be backward and inline.
   event = KeyDownEvent(ui::DomKey::ARROW_LEFT);
-  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event),
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *ltr_element),
             FocusgroupDirection::kBackwardInline);
 
   // Arrow up should be backward and block.
   event = KeyDownEvent(ui::DomKey::ARROW_UP);
-  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event),
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *ltr_element),
             FocusgroupDirection::kBackwardBlock);
 
   // When the shift key is pressed, even when combined with a valid arrow key,
   // it should return kNone.
   event = KeyDownEvent(ui::DomKey::ARROW_UP, nullptr, WebInputEvent::kShiftKey);
-  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event),
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *ltr_element),
             FocusgroupDirection::kNone);
 
   // When the ctrl key is pressed, even when combined with a valid arrow key, it
   // should return kNone.
   event =
       KeyDownEvent(ui::DomKey::ARROW_UP, nullptr, WebInputEvent::kControlKey);
-  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event),
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *ltr_element),
             FocusgroupDirection::kNone);
 
   // When the meta key (e.g.: CMD on mac) is pressed, even when combined with a
   // valid arrow key, it should return kNone.
   event = KeyDownEvent(ui::DomKey::ARROW_UP, nullptr, WebInputEvent::kMetaKey);
-  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event),
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *ltr_element),
             FocusgroupDirection::kNone);
 
   // Any other key than an arrow key should return kNone.
   event = KeyDownEvent(ui::DomKey::TAB);
-  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event),
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *ltr_element),
             FocusgroupDirection::kNone);
 }
 
+TEST_F(FocusgroupControllerTest, FocusgroupDirectionForEventRTL) {
+  SetBodyInnerHTML(R"HTML(
+    <div id=rtl dir="rtl">RTL element</div>
+  )HTML");
+  UpdateAllLifecyclePhasesForTest();
+  auto* rtl_element = GetElementById("rtl");
+  ASSERT_TRUE(rtl_element);
+
+  // In RTL horizontal-tb, inline direction is reversed:
+  // ArrowRight → backward inline (towards inline-start in RTL).
+  auto* event = KeyDownEvent(ui::DomKey::ARROW_RIGHT);
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *rtl_element),
+            FocusgroupDirection::kBackwardInline);
+
+  // ArrowLeft → forward inline (towards inline-end in RTL).
+  event = KeyDownEvent(ui::DomKey::ARROW_LEFT);
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *rtl_element),
+            FocusgroupDirection::kForwardInline);
+
+  // Block axis is unchanged in RTL horizontal-tb.
+  event = KeyDownEvent(ui::DomKey::ARROW_DOWN);
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *rtl_element),
+            FocusgroupDirection::kForwardBlock);
+
+  event = KeyDownEvent(ui::DomKey::ARROW_UP);
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *rtl_element),
+            FocusgroupDirection::kBackwardBlock);
+}
+
+TEST_F(FocusgroupControllerTest, FocusgroupDirectionForEventVerticalRL) {
+  SetBodyInnerHTML(R"HTML(
+    <div id=vrl style="writing-mode: vertical-rl">Vertical RL</div>
+  )HTML");
+  UpdateAllLifecyclePhasesForTest();
+  auto* vrl_element = GetElementById("vrl");
+  ASSERT_TRUE(vrl_element);
+
+  // In vertical-rl LTR, the inline axis is vertical and the block axis is
+  // horizontal. ArrowDown → forward inline, ArrowUp → backward inline,
+  // ArrowLeft → forward block, ArrowRight → backward block.
+  auto* event = KeyDownEvent(ui::DomKey::ARROW_DOWN);
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *vrl_element),
+            FocusgroupDirection::kForwardInline);
+
+  event = KeyDownEvent(ui::DomKey::ARROW_UP);
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *vrl_element),
+            FocusgroupDirection::kBackwardInline);
+
+  event = KeyDownEvent(ui::DomKey::ARROW_LEFT);
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *vrl_element),
+            FocusgroupDirection::kForwardBlock);
+
+  event = KeyDownEvent(ui::DomKey::ARROW_RIGHT);
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *vrl_element),
+            FocusgroupDirection::kBackwardBlock);
+}
+
+TEST_F(FocusgroupControllerTest, FocusgroupDirectionForEventVerticalLR) {
+  SetBodyInnerHTML(R"HTML(
+    <div id=vlr style="writing-mode: vertical-lr">Vertical LR</div>
+  )HTML");
+  UpdateAllLifecyclePhasesForTest();
+  auto* vlr_element = GetElementById("vlr");
+  ASSERT_TRUE(vlr_element);
+
+  // In vertical-lr LTR, the inline axis is vertical and the block axis is
+  // horizontal. ArrowDown → forward inline, ArrowUp → backward inline,
+  // ArrowRight → forward block, ArrowLeft → backward block.
+  auto* event = KeyDownEvent(ui::DomKey::ARROW_DOWN);
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *vlr_element),
+            FocusgroupDirection::kForwardInline);
+
+  event = KeyDownEvent(ui::DomKey::ARROW_UP);
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *vlr_element),
+            FocusgroupDirection::kBackwardInline);
+
+  event = KeyDownEvent(ui::DomKey::ARROW_RIGHT);
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *vlr_element),
+            FocusgroupDirection::kForwardBlock);
+
+  event = KeyDownEvent(ui::DomKey::ARROW_LEFT);
+  EXPECT_EQ(utils::FocusgroupDirectionForEvent(event, *vlr_element),
+            FocusgroupDirection::kBackwardBlock);
+}
+
 TEST_F(FocusgroupControllerTest, IsDirectionBackward) {
   ASSERT_FALSE(utils::IsDirectionBackward(FocusgroupDirection::kNone));
   ASSERT_TRUE(utils::IsDirectionBackward(FocusgroupDirection::kBackwardInline));
diff --git a/third_party/blink/renderer/core/page/focusgroup_controller_utils.cc b/third_party/blink/renderer/core/page/focusgroup_controller_utils.cc
index b2775c2c..01ae69a 100644
--- a/third_party/blink/renderer/core/page/focusgroup_controller_utils.cc
+++ b/third_party/blink/renderer/core/page/focusgroup_controller_utils.cc
@@ -17,6 +17,7 @@
 #include "third_party/blink/renderer/core/layout/table/layout_table_cell.h"
 #include "third_party/blink/renderer/core/page/focus_controller.h"
 #include "third_party/blink/renderer/core/page/grid_focusgroup_structure_info.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -151,25 +152,54 @@
 }  // namespace
 
 FocusgroupDirection FocusgroupControllerUtils::FocusgroupDirectionForEvent(
-    const KeyboardEvent* event) {
+    const KeyboardEvent* event,
+    const Element& focused_element) {
   DCHECK(event);
-  if (event->ctrlKey() || event->metaKey() || event->shiftKey())
+  if (event->ctrlKey() || event->metaKey() || event->shiftKey()) {
     return FocusgroupDirection::kNone;
-
-  const AtomicString key(event->key());
-  // TODO(bebeaudr): Support RTL. Will it be as simple as inverting the
-  // direction associated with the left and right arrows when in a RTL element?
-  if (key == keywords::kArrowDown) {
-    return FocusgroupDirection::kForwardBlock;
-  } else if (key == keywords::kArrowRight) {
-    return FocusgroupDirection::kForwardInline;
-  } else if (key == keywords::kArrowUp) {
-    return FocusgroupDirection::kBackwardBlock;
-  } else if (key == keywords::kArrowLeft) {
-    return FocusgroupDirection::kBackwardInline;
   }
 
-  return FocusgroupDirection::kNone;
+  // Determine the physical direction for the pressed arrow key.
+  const AtomicString key(event->key());
+  LogicalDirection logical_direction;
+  if (key == keywords::kArrowDown || key == keywords::kArrowRight ||
+      key == keywords::kArrowUp || key == keywords::kArrowLeft) {
+    // Resolve the writing direction from the focused element's computed style.
+    // This means arrow keys follow the element's local writing direction (e.g.,
+    // an RTL item inside an LTR focusgroup uses RTL key mappings). Falls back
+    // to horizontal-tb LTR when no style is available.
+    const ComputedStyle* style = focused_element.GetComputedStyle();
+    if (!style) {
+      return FocusgroupDirection::kNone;
+    }
+    WritingDirectionMode writing_direction = style->GetWritingDirection();
+
+    // Map the physical arrow key to a logical direction using the focused
+    // element's writing direction. This correctly handles RTL (left/right
+    // swap for inline) and vertical writing modes (axes swap).
+    if (key == keywords::kArrowDown) {
+      logical_direction = writing_direction.Bottom();
+    } else if (key == keywords::kArrowRight) {
+      logical_direction = writing_direction.Right();
+    } else if (key == keywords::kArrowUp) {
+      logical_direction = writing_direction.Top();
+    } else {
+      logical_direction = writing_direction.Left();
+    }
+  } else {
+    return FocusgroupDirection::kNone;
+  }
+
+  switch (logical_direction) {
+    case LogicalDirection::kInlineStart:
+      return FocusgroupDirection::kBackwardInline;
+    case LogicalDirection::kInlineEnd:
+      return FocusgroupDirection::kForwardInline;
+    case LogicalDirection::kBlockStart:
+      return FocusgroupDirection::kBackwardBlock;
+    case LogicalDirection::kBlockEnd:
+      return FocusgroupDirection::kForwardBlock;
+  }
 }
 
 bool FocusgroupControllerUtils::IsDirectionForward(
diff --git a/third_party/blink/renderer/core/page/focusgroup_controller_utils.h b/third_party/blink/renderer/core/page/focusgroup_controller_utils.h
index 11b995b..5b4782e 100644
--- a/third_party/blink/renderer/core/page/focusgroup_controller_utils.h
+++ b/third_party/blink/renderer/core/page/focusgroup_controller_utils.h
@@ -65,8 +65,14 @@
   STATIC_ONLY(FocusgroupControllerUtils);
 
  public:
+  // Maps the physical arrow key from |event| to a logical focusgroup
+  // direction, accounting for the writing direction (RTL, vertical writing
+  // modes) of |focused_element|. The caller passes the currently focused
+  // element so that arrow keys follow its local writing direction. Returns
+  // kNone for non-arrow keys or when modifier keys are held.
   static FocusgroupDirection FocusgroupDirectionForEvent(
-      const KeyboardEvent* event);
+      const KeyboardEvent* event,
+      const Element& focused_element);
   static bool IsDirectionBackward(FocusgroupDirection direction);
   static bool IsDirectionForward(FocusgroupDirection direction);
   static bool IsDirectionInline(FocusgroupDirection direction);
diff --git a/third_party/blink/renderer/core/page/touch_adjustment.cc b/third_party/blink/renderer/core/page/touch_adjustment.cc
index 492927e5..27d1a2fe 100644
--- a/third_party/blink/renderer/core/page/touch_adjustment.cc
+++ b/third_party/blink/renderer/core/page/touch_adjustment.cc
@@ -522,9 +522,12 @@
     }
   }
 
-  // As for HitTestResult.innerNode, we skip over pseudo-elements.
-  if (adjusted_node && adjusted_node->IsPseudoElement() &&
-      !adjusted_node->IsScrollMarkerPseudoElement()) {
+  // Resolve pseudos to their originating element unless they have activation
+  // behavior (::scroll-marker, ::scroll-button, ::interest-hint). Touch
+  // adjustment targets the clickable element, which for pseudos like
+  // ::before, ::after, ::marker is the originating element.
+  while (adjusted_node && adjusted_node->IsPseudoElement() &&
+         !To<PseudoElement>(adjusted_node)->HasActivationBehavior()) {
     adjusted_node = adjusted_node->ParentOrShadowHostNode();
   }
 
diff --git a/third_party/blink/renderer/core/paint/paint_layer_test.cc b/third_party/blink/renderer/core/paint/paint_layer_test.cc
index 1e236537..72b2acaa 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_test.cc
@@ -1956,13 +1956,16 @@
     <span id='target'></span>
   )HTML");
   Element* target = GetDocument().getElementById(AtomicString("target"));
+  PseudoElement* before = target->GetPseudoElement(kPseudoIdBefore);
   HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive);
   HitTestLocation location(PhysicalOffset(10, 10));
   HitTestResult result(request, location);
   GetDocument().GetLayoutView()->HitTest(location, result);
+  // InnerNodeForHitTesting() always resolves to the originating element so
+  // that selection and editing work correctly. The raw pseudo is stored in
+  // inner_possibly_pseudo_node_ and accessed via InnerPossiblyPseudoNode().
   EXPECT_EQ(target, result.InnerNode());
-  EXPECT_EQ(target->GetPseudoElement(kPseudoIdBefore),
-            result.InnerPossiblyPseudoNode());
+  EXPECT_EQ(before, result.InnerPossiblyPseudoNode());
 }
 
 TEST_P(PaintLayerTest, HitTestFirstLetterPseudoElement) {
@@ -2637,7 +2640,11 @@
   HitTestLocation location(PhysicalOffset(25, 20));
   HitTestResult result(request, location);
   GetDocument().GetLayoutView()->HitTest(location, result);
-  EXPECT_EQ(second_scroll_marker, result.InnerNode());
+  // InnerNodeForHitTesting() always resolves to the originating element to
+  // maintain the non-pseudo invariant on inner_node_. The pseudo itself is
+  // accessible via InnerPossiblyPseudoNode() for hover/dispatch purposes.
+  EXPECT_EQ(second_div, result.InnerNode());
+  EXPECT_EQ(second_scroll_marker, result.InnerPossiblyPseudoNode());
 
   MouseEvent& event = *MouseEvent::Create();
   event.SetType(event_type_names::kClick);
diff --git a/third_party/blink/renderer/core/paint/text_combine_painter.h b/third_party/blink/renderer/core/paint/text_combine_painter.h
index f13be8c..410c6e9 100644
--- a/third_party/blink/renderer/core/paint/text_combine_painter.h
+++ b/third_party/blink/renderer/core/paint/text_combine_painter.h
@@ -17,13 +17,6 @@
 // LayoutTextCombine.
 class TextCombinePainter final : public TextPainter {
  public:
-  TextCombinePainter(GraphicsContext& context,
-                     const SvgContextPaints* svg_context_paints,
-                     const gfx::Rect& visual_rect,
-                     const ComputedStyle& style,
-                     const LineRelativeOffset& text_origin);
-  ~TextCombinePainter();
-
   static void Paint(const PaintInfo& paint_info,
                     const PhysicalOffset& paint_offset,
                     const LayoutTextCombine& text_combine);
@@ -37,6 +30,13 @@
                           ETextDecorationSkipInk skip_ink) override;
 
  private:
+  TextCombinePainter(GraphicsContext& context,
+                     const SvgContextPaints* svg_context_paints,
+                     const gfx::Rect& visual_rect,
+                     const ComputedStyle& style,
+                     const LineRelativeOffset& text_origin);
+  ~TextCombinePainter();
+
   // Paints emphasis mark as for ideographic full stop character. Callers of
   // this function should rotate canvas to paint emphasis mark at left/right
   // side instead of top/bottom side.
diff --git a/third_party/blink/renderer/core/paint/text_fragment_painter.h b/third_party/blink/renderer/core/paint/text_fragment_painter.h
index 84947b7f..a6be7f5 100644
--- a/third_party/blink/renderer/core/paint/text_fragment_painter.h
+++ b/third_party/blink/renderer/core/paint/text_fragment_painter.h
@@ -28,7 +28,6 @@
   STACK_ALLOCATED();
 
  public:
-  explicit TextFragmentPainter(const InlineCursor& cursor) : cursor_(cursor) {}
   TextFragmentPainter(const InlineCursor& cursor,
                       const PhysicalOffset& parent_offset,
                       InlinePaintContext* inline_context)
diff --git a/third_party/blink/renderer/core/sanitizer/sanitizer_api.cc b/third_party/blink/renderer/core/sanitizer/sanitizer_api.cc
index a387708..4dc5f2c 100644
--- a/third_party/blink/renderer/core/sanitizer/sanitizer_api.cc
+++ b/third_party/blink/renderer/core/sanitizer/sanitizer_api.cc
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/core/dom/container_node.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/html/parser/fragment_parser_options.h"
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/sanitizer/sanitizer.h"
 #include "third_party/blink/renderer/core/sanitizer/sanitizer_builtins.h"
@@ -18,72 +19,37 @@
 
 namespace blink {
 
-// Note: SanitizerSafeInternal and SanitizerUnsafeInternal are mostly identical.
-//   But because SetHTMLOptions and SetHTMLUnsafeOptions are unrelated types (as
-//   far as C++ is concerned) they cannot easily be merged.
+namespace {
 
-const Sanitizer* SanitizerFromSafeOptions(SetHTMLOptions* options,
-                                          ExceptionState& exception_state) {
-  if (!options || !options->hasSanitizer()) {
-    // Default case: No dictionary, or dictionary without 'sanitizer' member.
-    return Sanitizer::Create(nullptr, Sanitizer::Mode::kSafe, exception_state);
+const Sanitizer* SanitizerFromOptions(const FragmentParserOptions& options,
+                                      Sanitizer::Mode mode,
+                                      ExceptionState& exception_state) {
+  if (!options.sanitizer_init()) {
+    return Sanitizer::Create(nullptr, mode, exception_state);
   }
 
-  if (options->sanitizer()->IsSanitizer()) {
-    // We already got a sanitizer.
-    return options->sanitizer()->GetAsSanitizer();
+  switch (options.sanitizer_init()->GetContentType()) {
+    case V8UnionSanitizerOrSanitizerConfigOrSanitizerPresets::ContentType::
+        kSanitizer:
+      return options.sanitizer_init()->GetAsSanitizer();
+    case V8UnionSanitizerOrSanitizerConfigOrSanitizerPresets::ContentType::
+        kSanitizerConfig:
+      return Sanitizer::Create(options.sanitizer_init()->GetAsSanitizerConfig(),
+                               mode, exception_state);
+    case V8UnionSanitizerOrSanitizerConfigOrSanitizerPresets::ContentType::
+        kSanitizerPresets:
+      return Sanitizer::Create(
+          options.sanitizer_init()->GetAsSanitizerPresets().AsEnum(),
+          exception_state);
   }
-
-  if (options->sanitizer()->IsSanitizerConfig()) {
-    // We need to create a Sanitizer from a given config.
-    return Sanitizer::Create(options->sanitizer()->GetAsSanitizerConfig(),
-                             Sanitizer::Mode::kSafe, exception_state);
-  }
-
-  if (options->sanitizer()->IsSanitizerPresets()) {
-    // Create a Sanitizer from a "preset" string.
-    return Sanitizer::Create(
-        options->sanitizer()->GetAsSanitizerPresets().AsEnum(),
-        exception_state);
-  }
-
-  // Default case: Dictionary with 'sanitizer' member but no (valid) value.
-  return Sanitizer::Create(nullptr, Sanitizer::Mode::kSafe, exception_state);
 }
-const Sanitizer* SanitizerFromUnsafeOptions(const SetHTMLUnsafeOptions* options,
-                                            ExceptionState& exception_state) {
-  if (!options || !options->hasSanitizer()) {
-    // Default case: No dictionary, or dictionary without 'sanitizer' member.
-    return Sanitizer::Create(nullptr, Sanitizer::Mode::kUnsafe,
-                             exception_state);
-  }
+}  // namespace
 
-  if (options->sanitizer()->IsSanitizer()) {
-    // We already got a sanitizer.
-    return options->sanitizer()->GetAsSanitizer();
-  }
-
-  if (options->sanitizer()->IsSanitizerConfig()) {
-    // We need to create a Sanitizer from a given config.
-    return Sanitizer::Create(options->sanitizer()->GetAsSanitizerConfig(),
-                             Sanitizer::Mode::kUnsafe, exception_state);
-  }
-
-  if (options->sanitizer()->IsSanitizerPresets()) {
-    // Create a Sanitizer from a "preset" string.
-    return Sanitizer::Create(
-        options->sanitizer()->GetAsSanitizerPresets().AsEnum(),
-        exception_state);
-  }
-
-  // Default case: Dictionary with 'sanitizer' member but not (valid) value.
-  return Sanitizer::Create(nullptr, Sanitizer::Mode::kUnsafe, exception_state);
-}
-
-void SanitizerAPI::SanitizeSafeInternal(const ContainerNode* context_element,
-                                        ContainerNode* root_element,
-                                        SetHTMLOptions* options,
-                                        ExceptionState& exception_state) {
+void SanitizerAPI::SanitizeInternal(Sanitizer::Mode mode,
+                                    const ContainerNode* context_element,
+                                    ContainerNode* root_element,
+                                    FragmentParserOptions options,
+                                    ExceptionState& exception_state) {
   // Per spec, we need to parse & sanitize into an inert (non-active) document.
   CHECK(!root_element->GetDocument().IsActive());
 
@@ -92,7 +58,7 @@
     return;
   }
 
-  if (context_element->IsElementNode()) {
+  if (mode == Sanitizer::Mode::kSafe && context_element->IsElementNode()) {
     const Element* real_element = To<Element>(context_element);
     if (real_element->TagQName() == html_names::kScriptTag ||
         real_element->TagQName() == svg_names::kScriptTag) {
@@ -102,44 +68,29 @@
   }
 
   const Sanitizer* sanitizer =
-      SanitizerFromSafeOptions(options, exception_state);
+      SanitizerFromOptions(options, mode, exception_state);
 
   if (exception_state.HadException()) {
     return;
   }
 
   CHECK(sanitizer);
-  sanitizer->SanitizeSafe(root_element);
+  switch (mode) {
+    case Sanitizer::Mode::kSafe:
+      sanitizer->SanitizeSafe(root_element);
+      break;
+    case Sanitizer::Mode::kUnsafe:
+      sanitizer->SanitizeUnsafe(root_element);
+      break;
+  }
 }
 
-void SanitizerAPI::SanitizeUnsafeInternal(const ContainerNode* context_element,
-                                          ContainerNode* root_element,
-                                          SetHTMLUnsafeOptions* options,
-                                          ExceptionState& exception_state) {
-  // Per spec, we need to parse & sanitize into an inert (non-active) document.
-  CHECK(!root_element->GetDocument().IsActive());
-
-  if (exception_state.HadException()) {
-    root_element->setTextContent("");
-    return;
-  }
-
-  const Sanitizer* sanitizer =
-      SanitizerFromUnsafeOptions(options, exception_state);
-  if (exception_state.HadException()) {
-    return;
-  }
-
-  CHECK(sanitizer);
-  sanitizer->SanitizeUnsafe(root_element);
-}
-
-StreamingSanitizer* SanitizerAPI::CreateStreamingSanitizerUnsafeInternal(
-    const SetHTMLUnsafeOptions* options,
+StreamingSanitizer* SanitizerAPI::CreateStreamingSanitizerInternal(
+    FragmentParserOptions options,
     const ContainerNode* context,
     ExceptionState& exception_state) {
   const Sanitizer* sanitizer =
-      SanitizerFromUnsafeOptions(options, exception_state);
+      SanitizerFromOptions(options, Sanitizer::Mode::kUnsafe, exception_state);
   if (exception_state.HadException()) {
     return nullptr;
   }
diff --git a/third_party/blink/renderer/core/sanitizer/sanitizer_api.h b/third_party/blink/renderer/core/sanitizer/sanitizer_api.h
index 1397291..4c174ef0 100644
--- a/third_party/blink/renderer/core/sanitizer/sanitizer_api.h
+++ b/third_party/blink/renderer/core/sanitizer/sanitizer_api.h
@@ -5,29 +5,27 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SANITIZER_SANITIZER_API_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_SANITIZER_SANITIZER_API_H_
 
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/sanitizer/sanitizer.h"
+
 // This file includes the entry points for the Sanitizer API.
 
 namespace blink {
 
 class ContainerNode;
-class SetHTMLOptions;
-class SetHTMLUnsafeOptions;
 class ExceptionState;
+class FragmentParserOptions;
 class StreamingSanitizer;
 
-class SanitizerAPI final {
+class CORE_EXPORT SanitizerAPI final {
  public:
-  static void SanitizeSafeInternal(const ContainerNode* context_element,
-                                   ContainerNode* root_element,
-                                   SetHTMLOptions* options,
-                                   ExceptionState& exception_state);
-  static void SanitizeUnsafeInternal(const ContainerNode* context_element,
-                                     ContainerNode* root_element,
-                                     SetHTMLUnsafeOptions* options,
-                                     ExceptionState& exception_state);
-
-  static StreamingSanitizer* CreateStreamingSanitizerUnsafeInternal(
-      const SetHTMLUnsafeOptions* options,
+  static void SanitizeInternal(Sanitizer::Mode mode,
+                               const ContainerNode* context_element,
+                               ContainerNode* root_element,
+                               FragmentParserOptions options,
+                               ExceptionState& exception_state);
+  static StreamingSanitizer* CreateStreamingSanitizerInternal(
+      FragmentParserOptions options,
       const ContainerNode* context,
       ExceptionState& exception_state);
 };
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.cc b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.cc
index 646a536..5c2c8dc 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.cc
@@ -170,7 +170,7 @@
   ScriptValue out;
   auto result =
       policy_options_->createParserOptions()->Invoke(nullptr, options);
-  if (!result.To(&out)) {
+  if (!result.To(&out) || out.IsNull() || out.IsUndefined()) {
     return nullptr;
   }
 
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_types_names.json5 b/third_party/blink/renderer/core/trustedtypes/trusted_types_names.json5
index e8181bc0..9f7db3d 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_types_names.json5
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_types_names.json5
@@ -26,9 +26,15 @@
     "Worker",
     "WorkerGlobalScope",
     "after",
+    "afterHTML",
+    "afterHTMLUnsafe",
     "append",
+    "appendHTML",
+    "appendHTMLUnsafe",
     "baseVal",
     "before",
+    "beforeHTML",
+    "beforeHTMLUnsafe",
     "codeBase",
     "constructor",
     "create",
@@ -45,10 +51,15 @@
     "parseFromString",
     "parseHTMLUnsafe",
     "prepend",
+    "prependHTML",
+    "prependHTMLUnsafe",
     "register",
     "replace",
     "replaceChildren",
     "replaceWith",
+    "replaceWithHTML",
+    "replaceWithHTMLUnsafe",
+    "setHTML",
     "setHTMLUnsafe",
     "setInterval",
     "setTimeout",
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
index 9fd6e41d..24430b5 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
@@ -4,13 +4,19 @@
 
 #include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
 
+#include <optional>
+
 #include "base/compiler_specific.h"
+#include "base/notreached.h"
 #include "base/unguessable_token.h"
 #include "third_party/blink/public/mojom/devtools/console_message.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/reporting/reporting.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_sanitizer_config.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_set_html_options.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_set_html_unsafe_options.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_sethtmlunsafeoptions_trustedparseroptions.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_string_trustedhtml.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_string_trustedscript.h"
@@ -20,6 +26,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_trustedscripturl_usvstring.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
+#include "third_party/blink/renderer/core/html/parser/fragment_parser_options.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/inspector/exception_metadata.h"
 #include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
@@ -59,6 +66,7 @@
   kScriptExecutionAndDefaultPolicyFailed,
   kTrustedHTMLParserOptionsTransform,
   kTrustedHTMLParserOptionsTransformAndNoDefaultPolicyExisted,
+  kTrustedHTMLParserOptionsTransformAndDefaultPolicyFailed,
 };
 
 // Strings to support building a sample, used in:
@@ -132,6 +140,10 @@
       CHECK(RuntimeEnabledFeatures::DocumentPatchingEnabled());
       return "The TrustedParserOptions parser options transform failed and no "
              "'default' policy for 'TrustedParserOptions' has been defined.";
+    case kTrustedHTMLParserOptionsTransformAndDefaultPolicyFailed:
+      CHECK(RuntimeEnabledFeatures::DocumentPatchingEnabled());
+      return "The TrustedParserOptions parser options transform failed and the "
+             "'default' policy failed to execute.";
   }
   NOTREACHED();
 }
@@ -624,44 +636,82 @@
   NOTREACHED();
 }
 
-[[nodiscard]] CORE_EXPORT const TrustedParserOptions*
-TrustedTypesCheckForParserOptions(
-    const V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions*
-        options_or_trusted_options,
-    const ExecutionContext* execution_context,
-    const AtomicString& interface_name,
-    const AtomicString& property_name,
-    ExceptionState& exception_state) {
-  if (options_or_trusted_options->IsTrustedParserOptions()) {
-    return options_or_trusted_options->GetAsTrustedParserOptions();
+[[nodiscard]] CORE_EXPORT std::optional<FragmentParserOptions>
+TrustedTypesCheckForParserOptions(FragmentParserOptions options,
+                                  MarkupInsertionMode insertion_mode,
+                                  const ExecutionContext* execution_context,
+                                  const AtomicString& interface_name,
+                                  const AtomicString& property_name,
+                                  ExceptionState& exception_state) {
+  if (options.trust_mode() == FragmentParserOptions::TrustMode::kTrusted) {
+    return options;
   }
 
-  const SetHTMLUnsafeOptions* options =
-      options_or_trusted_options->GetAsSetHTMLUnsafeOptions();
-
   if (!RequireTrustedTypesCheck(execution_context)) {
-    return MakeGarbageCollected<TrustedParserOptions>(options->sanitizer(),
-                                                      options->runScripts());
+    return options;
   }
 
+  // When streaming, we cannot use createHTML because the full HTML is not known
+  // at the time of checking. So in the streaming scenario, checking the parser
+  // options is a mandatory step. When setting HTML from a fragment (e.g.
+  // SetHTML), a trusted ParserOptions is optional.
+  const bool parser_options_required =
+      insertion_mode == MarkupInsertionMode::kStream;
+
   auto* default_policy = GetDefaultPolicy(execution_context);
   if (!default_policy) {
-    TrustedTypeFail(kTrustedHTMLParserOptionsTransform, execution_context,
-                    interface_name, property_name, exception_state,
-                    g_empty_string);
-    return nullptr;
+    if (parser_options_required &&
+        TrustedTypeFail(kTrustedHTMLParserOptionsTransform, execution_context,
+                        interface_name, property_name, exception_state,
+                        g_empty_string)) {
+      return std::nullopt;
+    }
+    return options;
   }
 
   if (!default_policy->HasCreateParserOptions()) {
-    TrustedTypeFail(kTrustedHTMLParserOptionsTransformAndNoDefaultPolicyExisted,
-                    execution_context, interface_name, property_name,
-                    exception_state, g_empty_string);
-    return nullptr;
+    if (parser_options_required &&
+        TrustedTypeFail(
+            kTrustedHTMLParserOptionsTransformAndNoDefaultPolicyExisted,
+            execution_context, interface_name, property_name, exception_state,
+            g_empty_string)) {
+      return std::nullopt;
+    }
+    return options;
   }
 
-  TryRethrowScope rethrow_scope(execution_context->GetIsolate(),
-                                exception_state);
-  return default_policy->createParserOptions(options, exception_state);
+  TrustedParserOptions* result = nullptr;
+  {
+    TryRethrowScope rethrow_scope(execution_context->GetIsolate(),
+                                  exception_state);
+
+    SetHTMLUnsafeOptions* unsafe_options_for_policy =
+        SetHTMLUnsafeOptions::Create(execution_context->GetIsolate());
+    unsafe_options_for_policy->setRunScripts(
+        options.run_scripts() ==
+        FragmentParserOptions::RunScripts::kRunScripts);
+    if (options.sanitizer_init()) {
+      unsafe_options_for_policy->setSanitizer(options.sanitizer_init());
+    }
+    result = default_policy->createParserOptions(unsafe_options_for_policy,
+                                                 exception_state);
+  }
+
+  if (exception_state.HadException()) {
+    return std::nullopt;
+  }
+
+  if (!result) {
+    if (TrustedTypeFail(
+            kTrustedHTMLParserOptionsTransformAndDefaultPolicyFailed,
+            execution_context, interface_name, property_name, exception_state,
+            g_empty_string)) {
+      return std::nullopt;
+    }
+    return options;
+  }
+
+  return FragmentParserOptions(result);
 }
 
 String TrustedTypesCheckForScript(const V8UnionStringOrTrustedScript* value,
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h
index b7f551c..daeed33 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_TYPES_UTIL_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_TYPES_UTIL_H_
 
+#include "third_party/blink/renderer/bindings/core/v8/v8_set_html_options.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_set_html_unsafe_options.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -17,11 +18,10 @@
 
 class ExceptionState;
 class ExecutionContext;
+class FragmentParserOptions;
 class QualifiedName;
 class ScriptValue;
 class ScriptState;
-class TrustedParserOptions;
-class V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions;
 class V8UnionStringOrTrustedScript;
 class V8UnionStringOrTrustedHTML;
 class V8UnionStringLegacyNullToEmptyStringOrTrustedHTML;
@@ -35,6 +35,8 @@
   kScriptURL,
 };
 
+enum class MarkupInsertionMode { kFragment, kStream };
+
 // Perform Trusted Type checks, with the IDL union types as input. All of these
 // will call String& versions below to do the heavy lifting.
 [[nodiscard]] CORE_EXPORT String
@@ -104,13 +106,13 @@
                               const AtomicString& property_name,
                               ExceptionState&);
 
-[[nodiscard]] CORE_EXPORT const TrustedParserOptions*
-TrustedTypesCheckForParserOptions(
-    const V8UnionSetHTMLUnsafeOptionsOrTrustedParserOptions*,
-    const ExecutionContext*,
-    const AtomicString& interface_name,
-    const AtomicString& property_name,
-    ExceptionState&);
+[[nodiscard]] CORE_EXPORT std::optional<FragmentParserOptions>
+TrustedTypesCheckForParserOptions(FragmentParserOptions options,
+                                  MarkupInsertionMode insertion_mode,
+                                  const ExecutionContext*,
+                                  const AtomicString& interface_name,
+                                  const AtomicString& property_name,
+                                  ExceptionState&);
 
 // Functionally equivalent to TrustedTypesCheckForScript(const String&, ...),
 // but with setup & error handling suitable for the asynchronous execution
diff --git a/third_party/blink/renderer/core/view_transition/page_swap_event.cc b/third_party/blink/renderer/core/view_transition/page_swap_event.cc
index 6c78aa0..41898a6 100644
--- a/third_party/blink/renderer/core/view_transition/page_swap_event.cc
+++ b/third_party/blink/renderer/core/view_transition/page_swap_event.cc
@@ -13,29 +13,12 @@
 #include "third_party/blink/renderer/core/loader/history_item.h"
 #include "third_party/blink/renderer/core/navigation_api/navigation_activation.h"
 #include "third_party/blink/renderer/core/navigation_api/navigation_api.h"
+#include "third_party/blink/renderer/core/navigation_api/navigation_type_util.h"
 #include "third_party/blink/renderer/core/view_transition/dom_view_transition.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 namespace blink {
-namespace {
-
-V8NavigationType::Enum TypeToEnum(
-    mojom::blink::NavigationTypeForNavigationApi type) {
-  switch (type) {
-    case mojom::blink::NavigationTypeForNavigationApi::kPush:
-      return V8NavigationType::Enum::kPush;
-    case mojom::blink::NavigationTypeForNavigationApi::kTraverse:
-      return V8NavigationType::Enum::kTraverse;
-    case mojom::blink::NavigationTypeForNavigationApi::kReplace:
-      return V8NavigationType::Enum::kReplace;
-    case mojom::blink::NavigationTypeForNavigationApi::kReload:
-      return V8NavigationType::Enum::kReload;
-  }
-  NOTREACHED();
-}
-
-}  // namespace
 
 PageSwapEvent::PageSwapEvent(
     Document& document,
@@ -81,8 +64,9 @@
     }
 
     activation_ = MakeGarbageCollected<NavigationActivation>();
-    activation_->Update(entry, from,
-                        TypeToEnum(page_swap_event_params->navigation_type));
+    activation_->Update(
+        entry, from,
+        ToV8NavigationType(page_swap_event_params->navigation_type));
   }
 }
 
diff --git a/third_party/blink/renderer/modules/ai/language_model.cc b/third_party/blink/renderer/modules/ai/language_model.cc
index 23a7fe33..455f496 100644
--- a/third_party/blink/renderer/modules/ai/language_model.cc
+++ b/third_party/blink/renderer/modules/ai/language_model.cc
@@ -318,7 +318,7 @@
     NOTREACHED() << "Append() should not invoke `OnStreaming()`";
   }
 
-  void OnQuotaOverflow() override {
+  void OnContextOverflow() override {
     if (overflow_callback_) {
       overflow_callback_.Run();
     }
@@ -655,7 +655,7 @@
       AIMetrics::AISessionType::kLanguageModel,
       BindOnce(&LanguageModel::ResolvePromiseOnComplete, WrapPersistent(this),
                WrapPersistent(resolver)),
-      BindRepeating(&LanguageModel::OnQuotaOverflow, WrapPersistent(this)),
+      BindRepeating(&LanguageModel::OnContextOverflow, WrapPersistent(this)),
       BindOnce(&RejectPromiseOnError<V8LanguageModelPromptResult>,
                WrapPersistent(resolver)),
       BindOnce(&RejectPromiseOnAbort<V8LanguageModelPromptResult>,
@@ -691,7 +691,7 @@
       script_state, options->getSignalOr(nullptr), task_runner_,
       AIMetrics::AISessionType::kLanguageModel,
       BindOnce(&LanguageModel::OnResponseComplete, WrapPersistent(this)),
-      BindRepeating(&LanguageModel::OnQuotaOverflow, WrapPersistent(this)));
+      BindRepeating(&LanguageModel::OnContextOverflow, WrapPersistent(this)));
 
   String json_schema = GetSchemaForInput(*processed_constraint, options);
   ConvertPromptInputsToMojo(
@@ -847,7 +847,7 @@
                       WrapPersistent(signal),
                       BindOnce(&LanguageModel::OnResponseComplete,
                                WrapWeakPersistent(this)),
-                      BindRepeating(&LanguageModel::OnQuotaOverflow,
+                      BindRepeating(&LanguageModel::OnContextOverflow,
                                     WrapWeakPersistent(this))),
       BindOnce(&RejectResolver, WrapPersistent(resolver)));
   return promise;
@@ -964,8 +964,15 @@
   return task_runner_;
 }
 
-void LanguageModel::OnQuotaOverflow() {
-  DispatchEvent(*Event::Create(event_type_names::kQuotaoverflow));
+void LanguageModel::OnContextOverflow() {
+  ExecutionContext* execution_context = GetExecutionContext();
+
+  if (execution_context &&
+      RuntimeEnabledFeatures::LanguageModelLegacyParamsAndAttributesEnabled(
+          execution_context)) {
+    DispatchEvent(*Event::Create(event_type_names::kQuotaoverflow));
+  }
+  DispatchEvent(*Event::Create(event_type_names::kContextoverflow));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/ai/language_model.h b/third_party/blink/renderer/modules/ai/language_model.h
index 4e347d7..6b1c360 100644
--- a/third_party/blink/renderer/modules/ai/language_model.h
+++ b/third_party/blink/renderer/modules/ai/language_model.h
@@ -54,6 +54,7 @@
   ExecutionContext* GetExecutionContext() const override;
 
   DEFINE_ATTRIBUTE_EVENT_LISTENER(quotaoverflow, kQuotaoverflow)
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(contextoverflow, kContextoverflow)
 
   // language_model.idl implementation.
   static ScriptPromise<LanguageModel> create(
@@ -119,7 +120,7 @@
       mojom::blink::ModelExecutionContextInfoPtr context_info);
   void OnResponseComplete(
       mojom::blink::ModelExecutionContextInfoPtr context_info);
-  void OnQuotaOverflow();
+  void OnContextOverflow();
 
   using ResolverOrStream =
       std::variant<ScriptPromiseResolverBase*, ReadableStream*>;
diff --git a/third_party/blink/renderer/modules/ai/language_model.idl b/third_party/blink/renderer/modules/ai/language_model.idl
index 22fb0be..c501740 100644
--- a/third_party/blink/renderer/modules/ai/language_model.idl
+++ b/third_party/blink/renderer/modules/ai/language_model.idl
@@ -135,7 +135,10 @@
   [MeasureAs=LanguageModel_Temperature, RuntimeEnabled=LanguageModelLegacyParamsAndAttributes]
   readonly attribute float temperature;
 
+  [MeasureAs=LanguageModel_OnQuotaOverflow, RuntimeEnabled=LanguageModelLegacyParamsAndAttributes]
   attribute EventHandler onquotaoverflow;
+  [MeasureAs=LanguageModel_OnContextOverflow]
+  attribute EventHandler oncontextoverflow;
 
   [
     MeasureAs=LanguageModel_Clone,
diff --git a/third_party/blink/renderer/modules/ai/model_execution_responder.cc b/third_party/blink/renderer/modules/ai/model_execution_responder.cc
index 4c16f42..ddbf505 100644
--- a/third_party/blink/renderer/modules/ai/model_execution_responder.cc
+++ b/third_party/blink/renderer/modules/ai/model_execution_responder.cc
@@ -111,7 +111,7 @@
     Cleanup();
   }
 
-  void OnQuotaOverflow() override {
+  void OnContextOverflow() override {
     if (overflow_callback_) {
       overflow_callback_.Run();
     }
@@ -164,7 +164,7 @@
       const String&,
       mojom::blink::ModelExecutionContextInfoPtr context_info)>
       complete_callback_;
-  // A callback invoked anytime the model's token quota is exceeded.
+  // A callback invoked anytime the model's token context window is exceeded.
   base::RepeatingClosure overflow_callback_;
   // Callback invoked on model error.
   base::OnceCallback<void(DOMException*)> error_callback_;
@@ -271,7 +271,7 @@
     Cleanup();
   }
 
-  void OnQuotaOverflow() override {
+  void OnContextOverflow() override {
     if (overflow_callback_) {
       overflow_callback_.Run();
     }
diff --git a/third_party/blink/renderer/modules/ai/model_execution_responder_test.cc b/third_party/blink/renderer/modules/ai/model_execution_responder_test.cc
index 864a8ca..afc9c60c9 100644
--- a/third_party/blink/renderer/modules/ai/model_execution_responder_test.cc
+++ b/third_party/blink/renderer/modules/ai/model_execution_responder_test.cc
@@ -92,7 +92,7 @@
   responder.set_disconnect_handler(disconnect_runloop.QuitClosure());
   responder->OnStreaming("a");
   responder->OnStreaming("b");
-  responder->OnQuotaOverflow();
+  responder->OnContextOverflow();
   responder->OnCompletion(
       mojom::blink::ModelExecutionContextInfo::New(kTestTokenNumber));
   // Check that the promise will be resolved with the "result" string.
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser.cc b/third_party/blink/renderer/modules/manifest/manifest_parser.cc
index ab2e819..ddd668ed 100644
--- a/third_party/blink/renderer/modules/manifest/manifest_parser.cc
+++ b/third_party/blink/renderer/modules/manifest/manifest_parser.cc
@@ -2196,6 +2196,13 @@
     return migrate_from_list;
   }
 
+  if (!manifest_->has_custom_id) {
+    AddErrorInfo(
+        "property 'migrate_from' ignored, manifest must specify an 'id' "
+        "property in order to receive a migration.");
+    return migrate_from_list;
+  }
+
   JSONArray* migrate_from_array = object->GetArray("migrate_from");
   if (!migrate_from_array) {
     AddErrorInfo(
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc b/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
index b770ffa..9830bd17 100644
--- a/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
+++ b/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
@@ -5569,25 +5569,37 @@
 
   // If non-array, empty and error.
   {
-    auto& manifest = ParseManifest(R"({"migrate_from": "not-an-array"})");
+    auto& manifest =
+        ParseManifest(R"({"id": "this_id", "migrate_from": "not-an-array"})");
     EXPECT_EQ(0u, manifest->migrate_from.size());
-    EXPECT_EQ(1u, GetErrorCount());
+    ASSERT_EQ(1u, GetErrorCount());
     EXPECT_EQ("property 'migrate_from' ignored, type array expected.",
               errors()[0]);
   }
 
+  // Valid array but no manifest id, empty and error.
+  {
+    auto& manifest = ParseManifest(R"({"migrate_from": ["app_id_1"]})");
+    EXPECT_EQ(0u, manifest->migrate_from.size());
+    ASSERT_EQ(1u, GetErrorCount());
+    EXPECT_EQ(
+        "property 'migrate_from' ignored, manifest must specify an 'id' "
+        "property in order to receive a migration.",
+        errors()[0]);
+  }
+
   // Array with non-strings and non-objects, ignore invalid types.
   {
     auto& manifest = ParseManifest(
-        R"({"migrate_from": ["app_id_1", 123, {"id": "app_id_2"}]})");
-    EXPECT_EQ(2u, manifest->migrate_from.size());
+        R"({"id": "this_id", "migrate_from": ["app_id_1", 123, {"id": "app_id_2"}]})");
+    ASSERT_EQ(2u, manifest->migrate_from.size());
     EXPECT_EQ("http://foo.com/app_id_1",
               manifest->migrate_from[0]->id.GetString());
     EXPECT_FALSE(manifest->migrate_from[0]->install_url.has_value());
     EXPECT_EQ("http://foo.com/app_id_2",
               manifest->migrate_from[1]->id.GetString());
     EXPECT_FALSE(manifest->migrate_from[1]->install_url.has_value());
-    EXPECT_EQ(1u, GetErrorCount());
+    ASSERT_EQ(1u, GetErrorCount());
     EXPECT_EQ("migrate_from entry ignored, type string or object expected.",
               errors()[0]);
   }
@@ -5595,8 +5607,8 @@
   // Valid array with mixed string and object with install_url.
   {
     auto& manifest = ParseManifest(
-        R"({"migrate_from": ["app_id_1", {"id": "app_id_2", "install_url": "http://foo.com/install"}]})");
-    EXPECT_EQ(2u, manifest->migrate_from.size());
+        R"({"id": "this_id", "migrate_from": ["app_id_1", {"id": "app_id_2", "install_url": "http://foo.com/install"}]})");
+    ASSERT_EQ(2u, manifest->migrate_from.size());
     EXPECT_EQ("http://foo.com/app_id_1",
               manifest->migrate_from[0]->id.GetString());
     EXPECT_FALSE(manifest->migrate_from[0]->install_url.has_value());
@@ -5611,9 +5623,9 @@
   // Object with missing id.
   {
     auto& manifest = ParseManifest(
-        R"({"migrate_from": [{"install_url": "http://example.com/install"}]})");
+        R"({"id": "this_id", "migrate_from": [{"install_url": "http://example.com/install"}]})");
     EXPECT_EQ(0u, manifest->migrate_from.size());
-    EXPECT_EQ(1u, GetErrorCount());
+    ASSERT_EQ(1u, GetErrorCount());
     EXPECT_EQ("migrate_from entry ignored, 'id' is missing or not a valid URL.",
               errors()[0]);
   }
@@ -5621,7 +5633,7 @@
   // Object with cross-origin install_url.
   {
     auto& manifest = ParseManifest(
-        R"({"migrate_from": [{"id": "http://foo.com/app", "install_url": "http://example.com/install"}]})");
+        R"({"id": "this_id", "migrate_from": [{"id": "http://foo.com/app", "install_url": "http://example.com/install"}]})");
     EXPECT_EQ(0u, manifest->migrate_from.size());
     EXPECT_EQ(1u, GetErrorCount());
     EXPECT_EQ(
@@ -5634,6 +5646,7 @@
   {
     auto& manifest = ParseManifest(
         R"({
+          "id": "this_id",
           "migrate_from": [
             {
               "id": "app_id_1",
@@ -5643,7 +5656,7 @@
             }
           ]
         })");
-    EXPECT_EQ(2u, manifest->migrate_from.size());
+    ASSERT_EQ(2u, manifest->migrate_from.size());
     EXPECT_EQ("http://foo.com/app_id_1",
               manifest->migrate_from[0]->id.GetString());
     ASSERT_TRUE(manifest->migrate_from[0]->install_url.has_value());
@@ -5659,6 +5672,7 @@
   {
     auto& manifest = ParseManifest(
         R"({
+          "id": "this_id",
           "migrate_from": [
             {
               "id": "app_id_1",
@@ -5674,7 +5688,7 @@
             }
           ]
         })");
-    EXPECT_EQ(4u, manifest->migrate_from.size());
+    ASSERT_EQ(4u, manifest->migrate_from.size());
     EXPECT_EQ(manifest->migrate_from[0]->behavior,
               mojom::blink::ManifestMigrationBehavior::kForce);
     EXPECT_EQ(manifest->migrate_from[1]->behavior,
@@ -5683,7 +5697,7 @@
               mojom::blink::ManifestMigrationBehavior::kSuggest);
     EXPECT_EQ(manifest->migrate_from[3]->behavior,
               mojom::blink::ManifestMigrationBehavior::kSuggest);
-    EXPECT_EQ(1u, GetErrorCount());
+    ASSERT_EQ(1u, GetErrorCount());
     EXPECT_EQ("behavior value 'invalid' ignored, unknown value.", errors()[0]);
   }
 }
diff --git a/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc b/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc
index bf91f4be..fca8b59 100644
--- a/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc
+++ b/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc
@@ -119,13 +119,14 @@
       audio_data, &elapsed_time_ms, &ntp_time_ms);
   TRACE_EVENT_END2("audio", "VoE::PullRenderData", "elapsed_time_ms",
                    elapsed_time_ms, "ntp_time_ms", ntp_time_ms);
-  if (elapsed_time_ms >= 0)
+  if (elapsed_time_ms >= 0) {
     *current_time = base::Milliseconds(elapsed_time_ms);
+  }
 
   // De-interleave each channel and convert to 32-bit floating-point
   // with nominal range -1.0 -> +1.0 to match the callback format.
   audio_bus->FromInterleaved<media::SignedInt16SampleTypeTraits>(
-      audio_data, audio_bus->frames());
+      render_buffer_);
 
   // Pass the render data to the playout sinks.
   base::AutoLock auto_lock(lock_);
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 90b57dd..0414624 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -2187,6 +2187,7 @@
     "animation/animation_translation_util_test.cc",
     "animation/compositor_animation_test.cc",
     "animation/timing_function_test.cc",
+    "audio/audio_array_test.cc",
     "audio/audio_destination_test.cc",
     "audio/audio_destination_uma_reporter_test.cc",
     "audio/audio_frame_stats_accumulator_test.cc",
diff --git a/third_party/blink/renderer/platform/audio/audio_array.h b/third_party/blink/renderer/platform/audio/audio_array.h
index 7fe1312..e1724478 100644
--- a/third_party/blink/renderer/platform/audio/audio_array.h
+++ b/third_party/blink/renderer/platform/audio/audio_array.h
@@ -31,9 +31,13 @@
 
 #include <string.h>
 
+#include <algorithm>
+#include <limits>
+
 #include "base/check_op.h"
+#include "base/containers/heap_array.h"
 #include "base/containers/span.h"
-#include "base/memory/raw_ptr.h"
+#include "base/memory/aligned_memory.h"
 #include "base/numerics/checked_math.h"
 #include "build/build_config.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -46,63 +50,70 @@
 class AudioArray final {
   USING_FAST_MALLOC(AudioArray);
 
+  struct BufferDeleter {
+    void operator()(T* ptr) const { Partitions::BufferAlignedFree(ptr); }
+  };
+  // Use a local alias for HeapArray with a custom deleter that uses the
+  // PartitionAlloc 'Buffer' partition. This is named PartitionHeapArray to
+  // avoid confusion with base::AlignedHeapArray, which uses a different
+  // deleter.
+  using PartitionHeapArray = base::HeapArray<T, BufferDeleter>;
+
  public:
-  AudioArray() : allocation_(nullptr), aligned_data_(nullptr), size_(0) {}
-  explicit AudioArray(size_t n)
-      : allocation_(nullptr), aligned_data_(nullptr), size_(0) {
-    Allocate(n);
-  }
+  AudioArray() = default;
+  explicit AudioArray(size_t n) { CHECK(TryAllocate(n)); }
   AudioArray(const AudioArray&) = delete;
   AudioArray& operator=(const AudioArray&) = delete;
 
-  ~AudioArray() { Partitions::FastFree(allocation_); }
+  ~AudioArray() = default;
 
   // It's OK to call Allocate() multiple times, but data will *not* be copied
   // from an initial allocation if re-allocated. Allocations are
   // zero-initialized.
-  void Allocate(size_t n) {
+  void Allocate(size_t n) { CHECK(TryAllocate(n)); }
+
+  bool TryAllocate(size_t n) {
     // Although n is a size_t, its true limit is max unsigned because we use
     // unsigned in zeroRange() and copyToRange(). Also check for integer
     // overflow.
-    CHECK_LE(n, std::numeric_limits<unsigned>::max() / sizeof(T));
+    if (n > std::numeric_limits<unsigned>::max() / sizeof(T)) {
+      return false;
+    }
+
+    if (n == 0) {
+      allocation_ = {};
+      return true;
+    }
+
     uint32_t initial_size = static_cast<uint32_t>(sizeof(T) * n);
 
-    // Minimmum alignment requirements for arrays so that we can use
-    // SIMD.
+    // Minimum alignment requirements for arrays so that we can use SIMD.
 #if defined(ARCH_CPU_X86_FAMILY)
     const unsigned kAlignment = 32;
 #else
     const unsigned kAlignment = 16;
 #endif
 
-    if (allocation_) {
-      Partitions::FastFree(allocation_);
+    allocation_ = {};
+
+    T* ptr = static_cast<T*>(Partitions::BufferTryAlignedZeroedMalloc(
+        initial_size, kAlignment, WTF_HEAP_PROFILER_TYPE_NAME(AudioArray<T>)));
+    if (!ptr) {
+      return false;
     }
 
-    // Always allocate extra space so that we are guaranteed to get
-    // the desired alignment.  Some memory is wasted, but it should be
-    // small since most arrays are probably at least 128 floats (or
-    // doubles).
-    unsigned total = base::CheckAdd(initial_size, kAlignment).ValueOrDie();
-    allocation_ = static_cast<T*>(Partitions::FastZeroedMalloc(
-        total, WTF_HEAP_PROFILER_TYPE_NAME(AudioArray<T>)));
-    CHECK(allocation_);
-
-    aligned_data_ = AlignedAddress(allocation_.get(), kAlignment);
-    size_ = static_cast<uint32_t>(n);
+    // SAFETY: `ptr` is allocated with `initial_size` which is `n * sizeof(T)`,
+    // so it has space for exactly `n` elements of type `T`.
+    allocation_ =
+        UNSAFE_BUFFERS(PartitionHeapArray::FromOwningPointer(ptr, n));
+    return true;
   }
 
-  T* Data() { return aligned_data_; }
-  const T* Data() const { return aligned_data_; }
-  uint32_t size() const { return size_; }
-  base::span<T> as_span() {
-    // SAFETY: Allocate() ensures `aligned_data_` and `size_` are safe.
-    return UNSAFE_BUFFERS(base::span(aligned_data_.get(), size_));
-  }
-  base::span<const T> as_span() const {
-    // SAFETY: Allocate() ensures `aligned_data_` and `size_` are safe.
-    return UNSAFE_BUFFERS(base::span(aligned_data_.get(), size_));
-  }
+  T* Data() { return allocation_.data(); }
+  const T* Data() const { return allocation_.data(); }
+  uint32_t size() const { return static_cast<uint32_t>(allocation_.size()); }
+  base::span<T> as_span() { return allocation_.as_span(); }
+  base::span<const T> as_span() const { return allocation_.as_span(); }
 
   T& at(size_t i) {
     // Note that although it is a size_t, `size_` is now guaranteed to be
@@ -155,16 +166,7 @@
   }
 
  private:
-  // Return an address that is aligned to an `alignment` boundary.
-  // `alignment` MUST be a power of two!
-  static T* AlignedAddress(T* address, intptr_t alignment) {
-    intptr_t value = reinterpret_cast<intptr_t>(address);
-    return reinterpret_cast<T*>((value + alignment - 1) & ~(alignment - 1));
-  }
-
-  raw_ptr<T, DanglingUntriaged> allocation_;
-  raw_ptr<T, DanglingUntriaged> aligned_data_;
-  uint32_t size_;
+  PartitionHeapArray allocation_;
 };
 
 typedef AudioArray<float> AudioFloatArray;
diff --git a/third_party/blink/renderer/platform/audio/audio_array_test.cc b/third_party/blink/renderer/platform/audio/audio_array_test.cc
new file mode 100644
index 0000000..e9b2dd8
--- /dev/null
+++ b/third_party/blink/renderer/platform/audio/audio_array_test.cc
@@ -0,0 +1,72 @@
+#include "build/build_config.h"
+#include "third_party/blink/renderer/platform/audio/audio_array.h"
+#include "third_party/blink/renderer/platform/audio/audio_bus.h"
+#include "third_party/blink/public/platform/web_audio_bus.h"
+#include "base/memory/aligned_memory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include <limits>
+
+namespace blink {
+
+TEST(AudioArrayTest, HandleOOM) {
+  AudioArray<float> array;
+  // Requesting an extremely large amount of memory to trigger OOM.
+  // With the fix, TryAllocate should return false instead of crashing.
+  // Use a value that is large but doesn't truncate to 0 on 32-bit systems.
+  bool success = array.TryAllocate(std::numeric_limits<size_t>::max());
+  EXPECT_FALSE(success);
+}
+
+TEST(AudioArrayTest, AlignmentAndFunctionality) {
+  const size_t kSize = 128;
+  AudioFloatArray array(kSize);
+
+  // Verify allocation success.
+  EXPECT_NE(array.Data(), nullptr);
+  EXPECT_EQ(array.size(), kSize);
+
+  // Verify alignment (16B or 32B depending on architecture).
+#if defined(ARCH_CPU_X86_FAMILY)
+  EXPECT_TRUE(base::IsAligned(array.Data(), 32));
+#else
+  EXPECT_TRUE(base::IsAligned(array.Data(), 16));
+#endif
+
+  // Verify zero-initialization (BufferTryZeroedMalloc requirement).
+  for (uint32_t i = 0; i < array.size(); ++i) {
+    EXPECT_EQ(array[i], 0.0f);
+  }
+
+  // Verify write/read functionality.
+  array[0] = 1.0f;
+  array[kSize - 1] = 2.0f;
+  EXPECT_EQ(array[0], 1.0f);
+  EXPECT_EQ(array[kSize - 1], 2.0f);
+}
+
+TEST(AudioArrayTest, ZeroSizeAllocation) {
+  AudioArray<float> array;
+  // Should return true and result in a size of 0.
+  EXPECT_TRUE(array.TryAllocate(0));
+  EXPECT_EQ(array.size(), 0u);
+  EXPECT_EQ(array.Data(), nullptr);
+}
+
+TEST(AudioBusTest, HandleOOM) {
+  // Requesting a large amount of memory to trigger OOM in one of the channels.
+  // TryCreate should return nullptr instead of crashing.
+  scoped_refptr<AudioBus> bus = AudioBus::TryCreate(2, 1ULL << 31);
+  EXPECT_EQ(bus, nullptr);
+}
+
+TEST(WebAudioBusTest, SafeCast) {
+  WebAudioBus web_bus;
+  // Requesting a length that is out of bounds for wtf_size_t (uint32_t).
+  // TryInitialize should return false instead of crashing.
+  // Use a value that is large but doesn't truncate to 0 on 32-bit systems.
+  bool success =
+      web_bus.TryInitialize(2, std::numeric_limits<size_t>::max(), 44100);
+  EXPECT_FALSE(success);
+}
+
+} // namespace blink
diff --git a/third_party/blink/renderer/platform/audio/audio_bus.cc b/third_party/blink/renderer/platform/audio/audio_bus.cc
index a221be30..91cb97cd8 100644
--- a/third_party/blink/renderer/platform/audio/audio_bus.cc
+++ b/third_party/blink/renderer/platform/audio/audio_bus.cc
@@ -63,6 +63,24 @@
   return base::AdoptRef(new AudioBus(number_of_channels, length, allocate));
 }
 
+scoped_refptr<AudioBus> AudioBus::TryCreate(unsigned number_of_channels,
+                                            uint32_t length) {
+  if (number_of_channels > kMaxBusChannels) {
+    return nullptr;
+  }
+
+  scoped_refptr<AudioBus> bus =
+      base::AdoptRef(new AudioBus(number_of_channels, length, false));
+
+  for (unsigned i = 0; i < number_of_channels; ++i) {
+    if (!bus->Channel(i)->TryAllocate(length)) {
+      return nullptr;
+    }
+  }
+
+  return bus;
+}
+
 AudioBus::AudioBus(unsigned number_of_channels, uint32_t length, bool allocate)
     : length_(length), sample_rate_(0) {
   channels_.ReserveInitialCapacity(number_of_channels);
diff --git a/third_party/blink/renderer/platform/audio/audio_bus.h b/third_party/blink/renderer/platform/audio/audio_bus.h
index d749e61c..fafa576 100644
--- a/third_party/blink/renderer/platform/audio/audio_bus.h
+++ b/third_party/blink/renderer/platform/audio/audio_bus.h
@@ -70,6 +70,8 @@
   static scoped_refptr<AudioBus> Create(unsigned number_of_channels,
                                         uint32_t length,
                                         bool allocate = true);
+  static scoped_refptr<AudioBus> TryCreate(unsigned number_of_channels,
+                                           uint32_t length);
 
   // Pass in 0.0 for sampleRate to use the file's sample-rate, otherwise a
   // sample-rate conversion to the requested sampleRate will be made (if it
diff --git a/third_party/blink/renderer/platform/audio/audio_channel.cc b/third_party/blink/renderer/platform/audio/audio_channel.cc
index 160c8ab..53404a1 100644
--- a/third_party/blink/renderer/platform/audio/audio_channel.cc
+++ b/third_party/blink/renderer/platform/audio/audio_channel.cc
@@ -38,6 +38,19 @@
 
 namespace blink {
 
+bool AudioChannel::TryAllocate(uint32_t length) {
+  if (!mem_buffer_) {
+    mem_buffer_ = std::make_unique<AudioFloatArray>();
+  }
+  if (!mem_buffer_->TryAllocate(length)) {
+    length_ = 0;
+    return false;
+  }
+  length_ = length;
+  silent_ = true;
+  return true;
+}
+
 void AudioChannel::ResizeSmaller(uint32_t new_length) {
   DCHECK_LE(new_length, length_);
   length_ = new_length;
diff --git a/third_party/blink/renderer/platform/audio/audio_channel.h b/third_party/blink/renderer/platform/audio/audio_channel.h
index 226550d..cbcaa61c 100644
--- a/third_party/blink/renderer/platform/audio/audio_channel.h
+++ b/third_party/blink/renderer/platform/audio/audio_channel.h
@@ -53,13 +53,17 @@
 
   // Manage storage for us.
   explicit AudioChannel(uint32_t length)
-      : length_(length), raw_pointer_(nullptr), silent_(true) {
-    mem_buffer_ = std::make_unique<AudioFloatArray>(length);
+      : length_(0), raw_pointer_(nullptr), silent_(true) {
+    CHECK(TryAllocate(length));
   }
 
   // A "blank" audio channel -- must call Set() before it's useful...
   AudioChannel() : length_(0), raw_pointer_(nullptr), silent_(true) {}
 
+  // Methods for internal allocation.
+  void Allocate(uint32_t length) { CHECK(TryAllocate(length)); }
+  bool TryAllocate(uint32_t length);
+
   // Redefine the memory for this channel. |storage| represents external memory
   // not managed by this object.
   void Set(float* storage, uint32_t length) {
diff --git a/third_party/blink/renderer/platform/exported/web_audio_bus.cc b/third_party/blink/renderer/platform/exported/web_audio_bus.cc
index ce10f8477..5afd30e 100644
--- a/third_party/blink/renderer/platform/exported/web_audio_bus.cc
+++ b/third_party/blink/renderer/platform/exported/web_audio_bus.cc
@@ -25,6 +25,7 @@
 #include "third_party/blink/public/platform/web_audio_bus.h"
 
 #include "base/memory/scoped_refptr.h"
+#include "base/numerics/safe_conversions.h"
 #include "media/base/audio_bus.h"
 #include "third_party/blink/renderer/platform/audio/audio_bus.h"
 
@@ -44,6 +45,29 @@
   private_ = audio_bus.get();
 }
 
+bool WebAudioBus::TryInitialize(unsigned number_of_channels,
+                                size_t length,
+                                double sample_rate) {
+  if (!base::IsValueInRangeForNumericType<wtf_size_t>(length)) {
+    return false;
+  }
+  wtf_size_t length_wtf = static_cast<wtf_size_t>(length);
+  scoped_refptr<AudioBus> audio_bus =
+      AudioBus::TryCreate(number_of_channels, length_wtf);
+  if (!audio_bus) {
+    return false;
+  }
+  audio_bus->SetSampleRate(sample_rate);
+
+  if (private_) {
+    private_->Release();
+  }
+
+  audio_bus->AddRef();
+  private_ = audio_bus.get();
+  return true;
+}
+
 void WebAudioBus::ResizeSmaller(size_t new_length) {
   DCHECK(private_);
   if (private_) {
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 87f42a4..be0fdc5 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1909,7 +1909,6 @@
       // https://issues.chromium.org/issues/357649033
       name: "CustomizableSelectListbox",
       status: "stable",
-      depends_on: ["SelectMobileDesktopParity"],
     },
     {
       // appearance:base-select for <select multiple size=1> with a picker.
@@ -3035,12 +3034,6 @@
       status: "experimental",
       base_feature: "none",
     },
-    // The `anchor` attribute, supported by both anchor positioning and the
-    // popover API.
-    {
-      name: "HTMLAnchorAttribute",
-      status: "experimental",
-    },
     // Additional default command/commandfor actions that aren't part of v1 of
     // commands. When this flag is disabled only v1 actions (popover and dialog
     // defaults) will work.
@@ -4947,16 +4940,6 @@
       status: "experimental",
     },
     {
-      // Makes the logic to choose between ListBox (in-page) or MenuList
-      // (dropdown) select element modes the same between mobile and desktop.
-      // Without this flag, mobile will always use MenuList and desktop always
-      // makes <select multiple> a ListBox.
-      // https://chromestatus.com/feature/5412736871825408
-      // https://issues.chromium.org/issues/439964654
-      name: "SelectMobileDesktopParity",
-      status: "stable",
-    },
-    {
       // Removes the forced overflow:hidden rules on the select element's
       // InnerElement unless the author specifies text-overflow:ellipsis. May
       // cause text to overlap with the dropdown indicator.
@@ -5203,7 +5186,7 @@
     },
     {
       name: "SoftNavigationEagerIcpEntryEmission",
-      status: "test",
+      status: "stable",
     },
     {
       name: "SoftNavigationHeuristics",
@@ -5701,6 +5684,15 @@
       status: "stable",
     },
     {
+      // When enabled, trusted types can be used to enforce sanitization &
+      // script running rules.
+      // For example, it can enforce that any HTML setter would go through a
+      // sanitizer. See https://github.com/w3c/trusted-types/issues/594
+      name: "TrustedTypesCreateParserOptions",
+      status: "experimental",
+      depends_on: ["SanitizerAPI", "SetHTMLCanRunScripts"],
+    },
+    {
       name: "TrustedTypesFromLiteral",
       status: "experimental",
       base_feature: "none",
diff --git a/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc b/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc
index 6804207..6ac548c 100644
--- a/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc
+++ b/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc
@@ -162,9 +162,16 @@
 
   // Only 16 bits per sample is ever used. The FromInterleaved() call should
   // be updated if that is no longer the case.
-  DCHECK_EQ(bits_per_sample, 16);
-  audio_bus_->FromInterleaved<media::SignedInt16SampleTypeTraits>(
-      reinterpret_cast<const int16_t*>(audio_data), frames_int);
+  CHECK_EQ(bits_per_sample, 16);
+
+  size_t total_samples =
+      base::CheckMul(number_of_channels, number_of_frames).ValueOrDie();
+
+  // SAFETY: Per interface contract, `data` should contain `number_of_frames` *
+  // `number_of_channels` samples, each sample being `sizeof(int16_t)` wide.
+  auto source = UNSAFE_BUFFERS(
+      base::span(reinterpret_cast<const int16_t*>(audio_data), total_samples));
+  audio_bus_->FromInterleaved<media::SignedInt16SampleTypeTraits>(source);
 
   media::AudioParameters params = MediaStreamAudioSource::GetAudioParameters();
   if (!params.IsValid() ||
diff --git a/third_party/blink/renderer/platform/wtf/allocator/partitions.cc b/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
index 8d54b59..b9a963d 100644
--- a/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
+++ b/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
@@ -32,8 +32,10 @@
 
 #include "base/allocator/partition_alloc_features.h"
 #include "base/allocator/partition_alloc_support.h"
+#include "base/compiler_specific.h"
 #include "base/debug/alias.h"
 #include "base/feature_list.h"
+#include "base/memory/aligned_memory.h"
 #include "base/no_destructor.h"
 #include "base/strings/safe_sprintf.h"
 #include "base/task/sequenced_task_runner.h"
@@ -336,11 +338,46 @@
 }
 
 // static
+void* Partitions::BufferTryAlignedZeroedMalloc(size_t n,
+                                               size_t alignment,
+                                               const char* type_name) {
+#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+  // TODO(crbug.com/487660033): PartitionAlloc's AlignedAlloc enforces alignment
+  // via a PA_CHECK. Under sanitizers (ASAN/TSAN), it redirects to standard
+  // malloc/calloc which only guarantees 8/16-byte alignment. Requesting higher
+  // alignment (e.g. 32-byte for SIMD) will cause a FATAL crash. We bypass this
+  // by using base::AlignedAlloc which is correctly hooked by sanitizers.
+  void* result = base::AlignedAlloc(n, alignment);
+  if (result) {
+    // SAFETY: base::AlignedAlloc(n, alignment) returns a valid pointer to n
+    // bytes.
+    UNSAFE_BUFFERS(memset(result, 0, n));
+  }
+  return result;
+#else
+  return BufferPartition()->AlignedAlloc<
+      partition_alloc::AllocFlags::kZeroFill |
+      partition_alloc::AllocFlags::kReturnNull>(alignment, n);
+#endif
+}
+
+// static
 void Partitions::BufferFree(void* p) {
   BufferPartition()->Free(p);
 }
 
 // static
+void Partitions::BufferAlignedFree(void* p) {
+#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+  // TODO(crbug.com/487660033): See the comment in BufferTryAlignedZeroedMalloc
+  // above for why this is necessary.
+  base::AlignedFree(p);
+#else
+  BufferPartition()->Free(p);
+#endif
+}
+
+// static
 void Partitions::BufferFreeWithSize(void* p, size_t size) {
   BufferPartition()->FreeWithSize(p, size);
 }
diff --git a/third_party/blink/renderer/platform/wtf/allocator/partitions.h b/third_party/blink/renderer/platform/wtf/allocator/partitions.h
index 014cf0a..14d2f51 100644
--- a/third_party/blink/renderer/platform/wtf/allocator/partitions.h
+++ b/third_party/blink/renderer/platform/wtf/allocator/partitions.h
@@ -88,7 +88,11 @@
 
   static void* PA_MALLOC_FN BufferMalloc(size_t n, const char* type_name);
   static void* BufferTryRealloc(void* p, size_t n, const char* type_name);
+  static void* PA_MALLOC_FN BufferTryAlignedZeroedMalloc(size_t n,
+                                                         size_t alignment,
+                                                         const char* type_name);
   static void BufferFree(void* p);
+  static void BufferAlignedFree(void* p);
   static void BufferFreeWithSize(void* p, size_t size);
   static size_t BufferPotentialCapacity(size_t n);
 
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index 0a08fc10..8f61dd71 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -703,6 +703,7 @@
             "cc::AnimationHost",
             "cc::AnimationIdProvider",
             "cc::AnimationTrigger",
+            "cc::AnimationTriggerDelegate",
             "cc::AnimationTimeline",
             "cc::FilterKeyframe",
             "cc::KeyframedFilterAnimationCurve",
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 5ba758d9..0e4f76b0 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1122,7 +1122,6 @@
 crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001b.html [ Failure ]
 crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001c.html [ Failure ]
 crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001d.html [ Failure ]
-crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001e.html [ Failure ]
 crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002a.html [ Failure ]
 crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002b.html [ Failure ]
 crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002c.html [ Failure ]
@@ -1136,6 +1135,7 @@
 crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001b.html [ Failure ]
 crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001c.html [ Failure ]
 crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001d.html [ Failure ]
+crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001e.html [ Failure ]
 crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002a.html [ Failure ]
 crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002b.html [ Failure ]
 crbug.com/1076027 external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002c.html [ Failure ]
@@ -1395,6 +1395,7 @@
 
 # Tests only passing with RunSnapshotPostLayoutStateSteps enabled
 crbug.com/384523570 virtual/run-snapshot-post-layout/external/wpt/scroll-animations/scroll-timelines/scroll-timeline-snapshotting.html [ Pass ]
+crbug.com/384523570 virtual/run-snapshot-post-layout/external/wpt/scroll-animations/scroll-timelines/updating-the-finished-state.html [ Pass Timeout ]
 crbug.com/384523570 virtual/run-snapshot-post-layout/fast/animation/scroll-animations/scroll-timeline-snapshotting.html [ Pass ]
 crbug.com/384523570 external/wpt/scroll-animations/scroll-timelines/scroll-timeline-snapshotting.html [ Failure ]
 crbug.com/384523570 fast/animation/scroll-animations/scroll-timeline-snapshotting.html [ Failure ]
@@ -1498,13 +1499,6 @@
 crbug.com/40268721 [ Mac ] external/wpt/html/semantics/popovers/light-dismiss-event-ordering.tentative.html [ Pass Timeout ]
 crbug.com/332331836 external/wpt/html/semantics/popovers/popover-attribute-basic.html [ Pass Timeout ]
 
-# HTML `anchor` attribute disabled virtual suite - these tests should fail:
-crbug.com/335223786 virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-anchor-inset-rule-display.tentative.html [ Failure ]
-crbug.com/335223786 virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-anchor-change-display.tentative.html [ Failure ]
-crbug.com/335223786 virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-anchor-display.tentative.html [ Failure ]
-crbug.com/335223786 virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-anchor-nested-display.tentative.html [ Failure ]
-crbug.com/335223786 virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-anchor-scroll-display.tentative.html [ Failure ]
-
 # Interestfor related tests
 crbug.com/326681249 external/wpt/html/semantics/interestfor/interestfor-svg-a-event-dispatch.tentative.html [ Failure ]
 crbug.com/326681249 external/wpt/html/semantics/interestfor/interestfor-pseudo-element-appearance.tentative.html [ Failure Pass ]
@@ -2832,6 +2826,9 @@
 # `-expected.txt` pathname is too long to check in.
 crbug.com/475042067 external/wpt/webrtc-encoded-transform/idlharness.https.window.html?include=(SFrameDecrypterStream|SFrameEncrypterStream|SFrameSenderTransform|SFrameReceiverTransform|SFrameTransform.\*) [ Failure ]
 
+# Unstable memory addresses dumped into test output.
+crbug.com/476344902 virtual/webui-browser/external/wpt/html/browsers/windows/nested-browsing-contexts/window-top.html [ Failure ]
+
 # ====== New tests from wpt-importer added here ======
 crbug.com/485394851 external/wpt/navigation-api/navigate-event/traverseTo-detach.html [ Crash ]
 crbug.com/484675900 [ Android ] external/wpt/webdriver/tests/classic/new_session/unhandled_prompt_behavior.py [ Timeout ]
diff --git a/third_party/blink/web_tests/TestLists/content_shell.filter b/third_party/blink/web_tests/TestLists/content_shell.filter
index 09d9fa7..e8e17e4 100644
--- a/third_party/blink/web_tests/TestLists/content_shell.filter
+++ b/third_party/blink/web_tests/TestLists/content_shell.filter
@@ -872,7 +872,6 @@
 
 # This times out on headless, on Mac only. It takes appreciably longer locally on my Mac on headless. Not sure why.
 external/wpt/html/semantics/popovers/popover-focus-2.html
-virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-focus-2.html
 
 # These are flaky on Mac. Judging by the other focus-related test in this list, I'm assuming
 # there is some kind of headless focus problem.
@@ -906,8 +905,6 @@
 virtual/fractional-scroll-offsets/external/wpt/css/css-position/sticky/position-sticky-large-top*
 virtual/gpu-rasterization/external/wpt/css/css-images/object-fit-*
 virtual/gpu-rasterization/external/wpt/css/css-images/object-view-box-fit-*
-virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-focus.html
-virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-hidden-display.html
 virtual/main-thread-clip-path-animation/external/wpt/css/css-masking/clip-path/animations/clip-path-animation-custom-timing-function.html
 virtual/main-thread-clip-path-animation/external/wpt/css/css-masking/clip-path/animations/clip-path-animation-fixed-position-rounding-error.html
 virtual/media-foundation-for-clear-dcomp/external/wpt/media-source/last-frame-dimensions.html
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 51e1bee..27a91070 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -1546,24 +1546,6 @@
     "expires": "Jun 1, 2025"
   },
   {
-    "prefix": "html-anchor-attribute-disabled",
-    "owners": [
-      "masonf@chromium.org"
-    ],
-    "platforms": [
-      "Linux",
-      "Mac",
-      "Win"
-    ],
-    "bases": [
-      "external/wpt/html/semantics/popovers"
-    ],
-    "args": [
-      "--disable-blink-features=HTMLAnchorAttribute"
-    ],
-    "expires": "Jun 1, 2026"
-  },
-  {
     "prefix": "http-cache-default-backend",
     "platforms": [
       "Linux",
diff --git a/third_party/blink/web_tests/dom/OWNERS b/third_party/blink/web_tests/dom/OWNERS
new file mode 100644
index 0000000..2757923f
--- /dev/null
+++ b/third_party/blink/web_tests/dom/OWNERS
@@ -0,0 +1 @@
+file://third_party/blink/renderer/core/dom/OWNERS
diff --git a/third_party/blink/web_tests/editing/OWNERS b/third_party/blink/web_tests/editing/OWNERS
new file mode 100644
index 0000000..8eddd50
--- /dev/null
+++ b/third_party/blink/web_tests/editing/OWNERS
@@ -0,0 +1 @@
+file://third_party/blink/renderer/core/editing/OWNERS
diff --git a/third_party/blink/web_tests/external/wpt/ai/language-model/language-model-create.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/ai/language-model/language-model-create.tentative.https.window.js
index 337f02c..ef9bc4d 100644
--- a/third_party/blink/web_tests/external/wpt/ai/language-model/language-model-create.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/ai/language-model/language-model-create.tentative.https.window.js
@@ -27,7 +27,7 @@
   assert_equals(
       typeof session.temperature, 'undefined');  // temperature is deprecated.
 
-  assert_equals(typeof session.onquotaoverflow, 'object');
+  assert_equals(typeof session.oncontextoverflow, 'object');
 }, 'LanguageModel.create() returns a valid object with default options');
 
 promise_test(async t => {
diff --git a/third_party/blink/web_tests/external/wpt/ai/language-model/language-model-prompt.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/ai/language-model/language-model-prompt.tentative.https.window.js
index a2f8d0a..8131574 100644
--- a/third_party/blink/web_tests/external/wpt/ai/language-model/language-model-prompt.tentative.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/ai/language-model/language-model-prompt.tentative.https.window.js
@@ -49,7 +49,7 @@
   await ensureLanguageModel();
   const session = await createLanguageModel();
   const promise = new Promise(resolve => {
-    session.addEventListener("quotaoverflow", resolve);
+    session.addEventListener('contextoverflow', resolve);
   });
   // Make sure there is something to evict.
   const kLongPrompt = kTestPrompt.repeat(10);
@@ -62,7 +62,7 @@
   const promptString = kLongPrompt.repeat(repeatCount);
   // The prompt promise succeeds, while causing older input to be evicted.
   await Promise.all([promise, session.prompt(promptString)]);
-}, 'The `quotaoverflow` event is fired when overall usage exceeds the quota');
+}, 'The `contextoverflow` event is fired when overall usage exceeds the context window');
 
 promise_test(async t => {
   await ensureLanguageModel();
@@ -71,4 +71,4 @@
   const requested = await session.measureContextUsage(promptString);
   await promise_rejects_quotaexceedederror(
       t, session.prompt(promptString), requested, session.contextWindow);
-}, 'Test that prompt input exceeding the total quota rejects');
+}, 'Test that prompt input exceeding the total context window rejects');
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-attr.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-attr.tentative.html
deleted file mode 100644
index 2c2d99c5..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-attr.tentative.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE html>
-<title>CSS Anchor Positioning: Transition when the anchor attribute changes</title>
-<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/">
-<link rel="help" href="https://github.com/whatwg/html/pull/9144">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<style>
-  #cb {
-    display: inline-block;
-    position: relative;
-    width: 250px;
-    height: 250px;
-    border: 1px solid black;
-  }
-  #anchor1, #anchor2 {
-    width: 100px;
-  }
-  #anchor1 {
-    background: wheat;
-    height: 50px;
-  }
-  #anchor2 {
-    background: tomato;
-    height: 90px;
-  }
-  #anchored {
-    position: absolute;
-    position-anchor: auto;
-    width: anchor-size(width);
-    height: anchor-size(height);
-    top: anchor(top);
-    left: anchor(right);
-    transition-duration: 1000s;
-    transition-timing-function: steps(2, start);
-    transition-property: top, height;
-    background-color: skyblue;
-  }
-</style>
-<div id=cb>
-  <div id=anchor1>Anchor1</div>
-  <div id=anchor2>Anchor2</div>
-  <div id=anchored anchor=anchor1></div>
-</div>
-<script>
-  test(() => {
-    assert_equals(anchored.offsetTop, 0);
-    assert_equals(anchored.offsetHeight, 50);
-    anchored.setAttribute('anchor', 'anchor2');
-    assert_equals(anchored.offsetTop, 25);
-    assert_equals(anchored.offsetHeight, 70);
-  }, 'Transition when the anchor attribute changes');
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/display-none-dont-cancel-pseudo.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-animations/display-none-dont-cancel-pseudo.tentative-expected.txt
new file mode 100644
index 0000000..15da503f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-animations/display-none-dont-cancel-pseudo.tentative-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] A CSS Animation on a pseudo-element animating to "display: none" with "fill: forwards" remains active after animation completion.
+  assert_equals: The animation remains after completion expected 1 but got 0
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001a-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001a-ref.html
index f869c1d..9f46e1a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001a-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001a-ref.html
@@ -84,14 +84,20 @@
 
 <!-- just to sanity check that `grid-lanes` behaves as `none` in the column axis in this case: -->
 
-<grid style="grid:grid-lanes/none">
+<grid class="rows">
+ <grid-lanes-track>
   <item class="nth-1">1</item>
-  <item class="purple js">2</item>
+  <item>5</item>
+ </grid-lanes-track>
+ <grid-lanes-track>
+  <item class="purple">2</item>
   <item>3</item>
-  <subgrid style="grid:grid-lanes/none">
-    <item class="nth-1">4a</item>
-    <item style="margin-right:15px" class="purple js">4b</item>
+  <subgrid>
+    <item class="nth-1" style="grid-row:span 2; align-self:start">4a</item>
+    <item class="purple">4b</item>
+    <item style="grid-column:2">4c</item>
   </subgrid>
+ </grid-lanes-track>
 </grid>
 
 </body></html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001a.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001a.html
index 3774c87a..0c2df0e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001a.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001a.html
@@ -14,19 +14,15 @@
   color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
-  grid-template-rows: 50px 80px 40px;
+  grid-template-columns: 50px 80px 40px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-template-columns: 50px 80px 40px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -41,27 +37,24 @@
 subgrid {
   display: grid;
   grid: subgrid / subgrid;
-  grid-row: 2 / span 2;
+  grid-column: 2 / span 2;
   grid-gap: 8px 20px;
   background: yellow;
-}
-.rows > subgrid {
-  grid-row: initial;
-  grid-column: 2 / span 2;
+  flow-tolerance: 0px;
 }
 </style>
 </head>
 <body>
-
-
-<grid>
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
   <subgrid>
     <item>4a</item>
-    <item style="margin-right:15px">4b</item>
+    <item>4b</item>
+    <item>4c</item>
   </subgrid>
-</grid>
-
-</body></html>
+  <item>5</item>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001b-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001b-ref.html
index fa902b1..3e0b5cb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001b-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001b-ref.html
@@ -84,7 +84,7 @@
 
 <!-- just to sanity check that `grid-lanes` behaves as `none` in the column axis in this case: -->
 
-<grid>
+<grid class="rows">
  <grid-lanes-track>
   <item class="nth-1">1</item>
   <item>5</item>
@@ -92,9 +92,9 @@
  <grid-lanes-track>
   <item class="purple">2</item>
   <item>3</item>
-  <subgrid>
-    <item class="nth-1" style="grid-column:span 2">4a</item>
-    <item class="purple js">4b</item>
+  <subgrid style="grid:auto/subgrid">
+    <item class="nth-1">4a</item>
+    <item class="purple">4b</item>
     <item>4c</item>
   </subgrid>
  </grid-lanes-track>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001b.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001b.html
index 732486c5..7526d831 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001b.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001b.html
@@ -14,19 +14,15 @@
   color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
-  grid-template-rows: 50px 80px 40px;
+  grid-template-columns: 50px 80px 40px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-template-columns: 50px 80px 40px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -41,29 +37,23 @@
 subgrid {
   display: grid;
   grid: subgrid / subgrid;
-  grid-row: 2 / span 2;
+  grid-column: 2 / span 2;
   grid-gap: 8px 20px;
   background: yellow;
 }
-.rows > subgrid {
-  grid-row: initial;
-  grid-column: 2 / span 2;
-}
 </style>
 </head>
 <body>
-
-
-<grid>
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid>
+  <subgrid style="grid:auto/subgrid">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001c-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001c-ref.html
index 9104ea2..6a8ee73 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001c-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001c-ref.html
@@ -84,7 +84,7 @@
 
 <!-- just to sanity check that `grid-lanes` behaves as `none` in the column axis in this case: -->
 
-<grid>
+<grid class="rows">
  <grid-lanes-track>
   <item class="nth-1">1</item>
   <item>5</item>
@@ -92,9 +92,9 @@
  <grid-lanes-track>
   <item class="purple">2</item>
   <item>3</item>
-  <subgrid style="grid:subgrid/auto">
+  <subgrid style="grid:auto/subgrid; grid-auto-flow:column">
     <item class="nth-1">4a</item>
-    <item class="purple js">4b</item>
+    <item class="purple">4b</item>
     <item>4c</item>
   </subgrid>
  </grid-lanes-track>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001c.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001c.html
index d52db5e9..5ed2d03 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001c.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001c.html
@@ -14,19 +14,15 @@
   color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
-  grid-template-rows: 50px 80px 40px;
+  grid-template-columns: 50px 80px 40px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-template-columns: 50px 80px 40px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -41,29 +37,23 @@
 subgrid {
   display: grid;
   grid: subgrid / subgrid;
-  grid-row: 2 / span 2;
+  grid-column: 2 / span 2;
   grid-gap: 8px 20px;
   background: yellow;
 }
-.rows > subgrid {
-  grid-row: initial;
-  grid-column: 2 / span 2;
-}
 </style>
 </head>
 <body>
-
-
-<grid>
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid:subgrid/auto">
+  <subgrid style="grid:auto/subgrid; grid-auto-flow:column">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001d-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001d-ref.html
index 5e99bfb..3a4e959b9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001d-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001d-ref.html
@@ -84,7 +84,7 @@
 
 <!-- just to sanity check that `grid-lanes` behaves as `none` in the column axis in this case: -->
 
-<grid>
+<grid class="rows">
  <grid-lanes-track>
   <item class="nth-1">1</item>
   <item>5</item>
@@ -92,9 +92,9 @@
  <grid-lanes-track>
   <item class="purple">2</item>
   <item>3</item>
-  <subgrid style="grid:subgrid/auto; grid-auto-flow:column">
+  <subgrid style="grid:auto auto/subgrid">
     <item class="nth-1">4a</item>
-    <item class="purple js">4b</item>
+    <item class="purple">4b</item>
     <item>4c</item>
   </subgrid>
  </grid-lanes-track>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001d.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001d.html
index 0bc94a2..e048836 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001d.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001d.html
@@ -14,19 +14,15 @@
   color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
-  grid-template-rows: 50px 80px 40px;
+  grid-template-columns: 50px 80px 40px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-template-columns: 50px 80px 40px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -41,29 +37,23 @@
 subgrid {
   display: grid;
   grid: subgrid / subgrid;
-  grid-row: 2 / span 2;
+  grid-column: 2 / span 2;
   grid-gap: 8px 20px;
   background: yellow;
 }
-.rows > subgrid {
-  grid-row: initial;
-  grid-column: 2 / span 2;
-}
 </style>
 </head>
 <body>
-
-
-<grid>
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid:subgrid/auto; grid-auto-flow:column">
+  <subgrid style="grid:auto auto/subgrid">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002a-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002a-ref.html
index a9f9a58f..0e6a720 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002a-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002a-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid>
+<grid class="rows">
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid: none">
+  <subgrid>
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002a.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002a.html
index b5718e9..12cc52c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002a.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002a.html
@@ -14,20 +14,15 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
-  grid-template-rows: 40px 30px 20px;
+  grid-template-columns: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,35 +42,20 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid>
-  <item>1</item>
-  <item>2</item>
-  <item>3</item>
-  <subgrid>
-    <item>4a</item>
-    <item>4b</item>
-    <item>4c</item>
+<grid-lanes>
+  <item style="height: 24px;">1</item>
+  <item style="height: 40px;">2</item>
+  <item style="height: 40px;">3</item>
+  <subgrid style="height: calc(30px + 4px + 20px);">
+    <item style="height: 13px;">4a</item>
+    <item style="height: 29px;">4b</item>
+    <item style="height: 19px;">4c</item>
   </subgrid>
-  <item>5</item>
-</grid>
-
-</body></html>
+  <item style="height: 30px;">5</item>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002b-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002b-ref.html
index 58d1054..56609cb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002b-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002b-ref.html
@@ -15,6 +15,7 @@
 grid {
   display: inline-grid;
   grid-template-rows: 40px 30px 20px;
+  grid-template-columns: grid-lanes;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
@@ -24,6 +25,7 @@
 }
 .rows {
   grid-template-columns: 40px 30px 20px;
+  grid-template-rows: grid-lanes;
   grid-auto-flow: row;
 }
 item {
@@ -65,7 +67,7 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid>
+<grid class="rows">
   <item>1</item>
   <subgrid class="definite">
     <item>4a</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002b.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002b.html
index c56f3884..5a88f9e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002b.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002b.html
@@ -14,20 +14,15 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
-  grid-template-rows: 40px 30px 20px;
+  grid-template-columns: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,26 +42,11 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid>
+<grid-lanes>
   <item>1</item>
   <subgrid>
     <item>4a</item>
@@ -76,6 +56,6 @@
   <item>2</item>
   <item>3</item>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002c-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002c-ref.html
index d309201..041e313 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002c-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002c-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid>
+<grid class="rows">
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid: 29px 19px">
+  <subgrid style="grid: none / 27px 17px">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002c.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002c.html
index 5f27962..c0f770f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002c.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002c.html
@@ -14,20 +14,15 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
-  grid-template-rows: 40px 30px 20px;
+  grid-template-columns: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -48,25 +43,13 @@
   background: yellow;
 }
 subgrid.definite {
-  grid-row-start:2;
-}
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
   grid-column-start:2;
 }
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid>
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
@@ -76,6 +59,6 @@
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002d-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002d-ref.html
index f66335d..02afb6c7 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002d-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002d-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid>
+<grid class="rows">
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid class="extent" style="grid: 39px 28px 19px">
+  <subgrid class="extent" style="grid: none / 37px 24px 17px">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002d.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002d.html
index 739e0214..216b4fc 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002d.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002d.html
@@ -14,20 +14,15 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
-  grid-template-rows: 40px 30px 20px;
+  grid-template-columns: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,26 +42,15 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
 subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
   grid-row: auto/span 2;
   grid-column: auto/span 3;
 }
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid>
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
@@ -76,6 +60,6 @@
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002e-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002e-ref.html
index e24e18a..5f279cb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002e-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002e-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid>
+<grid class="rows">
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid: none">
+  <subgrid style="grid: none / none">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002e.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002e.html
index c850577..f1e65de 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002e.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002e.html
@@ -14,20 +14,15 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
-  grid-template-rows: 40px 30px 20px;
+  grid-template-columns: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,35 +42,20 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid>
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid: subgrid / none">
+  <subgrid style="grid: none / subgrid">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002f-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002f-ref.html
index 78bd6fea..744c44b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002f-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002f-ref.html
@@ -65,7 +65,7 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid>
+<grid class="rows">
   <item>1</item>
   <subgrid class="definite">
     <item>4a</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002f.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002f.html
index 6f612f8..0277b7f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002f.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002f.html
@@ -14,20 +14,15 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
-  grid-template-rows: 40px 30px 20px;
+  grid-template-columns: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,28 +42,13 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid>
+<grid-lanes>
   <item>1</item>
-  <subgrid style="grid: subgrid / none">
+  <subgrid style="grid: none / subgrid">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
@@ -76,6 +56,6 @@
   <item>2</item>
   <item>3</item>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002g-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002g-ref.html
index 250165a..cdbfd22a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002g-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002g-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid>
+<grid class="rows">
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid: 29px 19px">
+  <subgrid style="grid: none / 27px 17px">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002g.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002g.html
index 08a9d53..32220cf 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002g.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002g.html
@@ -14,20 +14,15 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
-  grid-template-rows: 40px 30px 20px;
+  grid-template-columns: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -48,25 +43,13 @@
   background: yellow;
 }
 subgrid.definite {
-  grid-row-start:2;
-}
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
   grid-column-start:2;
 }
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid>
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
@@ -76,6 +59,6 @@
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002h-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002h-ref.html
index 16e337c7..86df33d0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002h-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002h-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid>
+<grid class="rows">
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid class="extent" style="grid: 39px 28px 19px">
+  <subgrid class="extent" style="grid: none / 37px 24px 17px">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002h.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002h.html
index e91785c..32ca058 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002h.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002h.html
@@ -14,20 +14,15 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
-  grid-template-rows: 40px 30px 20px;
+  grid-template-columns: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,26 +42,15 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
 subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
   grid-row: auto/span 2;
   grid-column: auto/span 3;
 }
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid>
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
@@ -76,6 +60,6 @@
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002i-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002i-ref.html
index 76bb93c..030b0e6 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002i-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002i-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid>
+<grid class="rows">
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid: auto auto">
+  <subgrid style="grid: none / auto auto">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002i.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002i.html
index 6731311b..d0c5f33 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002i.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-002i.html
@@ -14,20 +14,15 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
-  grid-template-rows: 40px 30px 20px;
+  grid-template-columns: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,35 +42,20 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid>
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid: auto auto / subgrid">
+  <subgrid style="grid: subgrid / auto auto">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001a-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001a-ref.html
index 9f46e1a..f869c1d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001a-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001a-ref.html
@@ -84,20 +84,14 @@
 
 <!-- just to sanity check that `grid-lanes` behaves as `none` in the column axis in this case: -->
 
-<grid class="rows">
- <grid-lanes-track>
+<grid style="grid:grid-lanes/none">
   <item class="nth-1">1</item>
-  <item>5</item>
- </grid-lanes-track>
- <grid-lanes-track>
-  <item class="purple">2</item>
+  <item class="purple js">2</item>
   <item>3</item>
-  <subgrid>
-    <item class="nth-1" style="grid-row:span 2; align-self:start">4a</item>
-    <item class="purple">4b</item>
-    <item style="grid-column:2">4c</item>
+  <subgrid style="grid:grid-lanes/none">
+    <item class="nth-1">4a</item>
+    <item style="margin-right:15px" class="purple js">4b</item>
   </subgrid>
- </grid-lanes-track>
 </grid>
 
 </body></html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001a.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001a.html
index 20a7945..08b86426 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001a.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001a.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 50px 80px 40px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,9 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-template-columns: 50px 80px 40px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -44,27 +40,18 @@
   grid-row: 2 / span 2;
   grid-gap: 8px 20px;
   background: yellow;
-  flow-tolerance: 0px;
-}
-.rows > subgrid {
-  grid-row: initial;
-  grid-column: 2 / span 2;
 }
 </style>
 </head>
 <body>
-
-
-<grid class="rows">
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
   <subgrid>
     <item>4a</item>
-    <item>4b</item>
-    <item>4c</item>
+    <item style="margin-right:15px">4b</item>
   </subgrid>
-  <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001b-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001b-ref.html
index 3e0b5cb..fa902b1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001b-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001b-ref.html
@@ -84,7 +84,7 @@
 
 <!-- just to sanity check that `grid-lanes` behaves as `none` in the column axis in this case: -->
 
-<grid class="rows">
+<grid>
  <grid-lanes-track>
   <item class="nth-1">1</item>
   <item>5</item>
@@ -92,9 +92,9 @@
  <grid-lanes-track>
   <item class="purple">2</item>
   <item>3</item>
-  <subgrid style="grid:auto/subgrid">
-    <item class="nth-1">4a</item>
-    <item class="purple">4b</item>
+  <subgrid>
+    <item class="nth-1" style="grid-column:span 2">4a</item>
+    <item class="purple js">4b</item>
     <item>4c</item>
   </subgrid>
  </grid-lanes-track>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001b.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001b.html
index 46a94959..21c6a4e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001b.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001b.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 50px 80px 40px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,9 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-template-columns: 50px 80px 40px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -45,25 +41,19 @@
   grid-gap: 8px 20px;
   background: yellow;
 }
-.rows > subgrid {
-  grid-row: initial;
-  grid-column: 2 / span 2;
-}
 </style>
 </head>
 <body>
-
-
-<grid class="rows">
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid:auto/subgrid">
+  <subgrid>
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001c-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001c-ref.html
index 6a8ee73..9104ea2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001c-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001c-ref.html
@@ -84,7 +84,7 @@
 
 <!-- just to sanity check that `grid-lanes` behaves as `none` in the column axis in this case: -->
 
-<grid class="rows">
+<grid>
  <grid-lanes-track>
   <item class="nth-1">1</item>
   <item>5</item>
@@ -92,9 +92,9 @@
  <grid-lanes-track>
   <item class="purple">2</item>
   <item>3</item>
-  <subgrid style="grid:auto/subgrid; grid-auto-flow:column">
+  <subgrid style="grid:subgrid/auto">
     <item class="nth-1">4a</item>
-    <item class="purple">4b</item>
+    <item class="purple js">4b</item>
     <item>4c</item>
   </subgrid>
  </grid-lanes-track>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001c.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001c.html
index 772a6db..8387e07 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001c.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001c.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 50px 80px 40px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,9 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-template-columns: 50px 80px 40px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -45,25 +41,19 @@
   grid-gap: 8px 20px;
   background: yellow;
 }
-.rows > subgrid {
-  grid-row: initial;
-  grid-column: 2 / span 2;
-}
 </style>
 </head>
 <body>
-
-
-<grid class="rows">
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid:auto/subgrid; grid-auto-flow:column">
+  <subgrid style="grid:subgrid/auto">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001d-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001d-ref.html
index 3a4e959b9..5e99bfb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001d-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001d-ref.html
@@ -84,7 +84,7 @@
 
 <!-- just to sanity check that `grid-lanes` behaves as `none` in the column axis in this case: -->
 
-<grid class="rows">
+<grid>
  <grid-lanes-track>
   <item class="nth-1">1</item>
   <item>5</item>
@@ -92,9 +92,9 @@
  <grid-lanes-track>
   <item class="purple">2</item>
   <item>3</item>
-  <subgrid style="grid:auto auto/subgrid">
+  <subgrid style="grid:subgrid/auto; grid-auto-flow:column">
     <item class="nth-1">4a</item>
-    <item class="purple">4b</item>
+    <item class="purple js">4b</item>
     <item>4c</item>
   </subgrid>
  </grid-lanes-track>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001d.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001d.html
index 35941038..43455412 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001d.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001d.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 50px 80px 40px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,9 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-template-columns: 50px 80px 40px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -45,25 +41,19 @@
   grid-gap: 8px 20px;
   background: yellow;
 }
-.rows > subgrid {
-  grid-row: initial;
-  grid-column: 2 / span 2;
-}
 </style>
 </head>
 <body>
-
-
-<grid class="rows">
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid:auto auto/subgrid">
+  <subgrid style="grid:subgrid/auto; grid-auto-flow:column">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001e-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001e-ref.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001e-ref.html
rename to third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001e-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001e.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001e.html
similarity index 87%
rename from third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001e.html
rename to third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001e.html
index 718b36ae..4c49a039 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/column/grid-lanes-subgrid-001e.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-001e.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 50px 80px 40px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,9 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-template-columns: 50px 80px 40px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -45,16 +41,10 @@
   grid-gap: 8px 20px;
   background: yellow;
 }
-.rows > subgrid {
-  grid-row: initial;
-  grid-column: 2 / span 2;
-}
 </style>
 </head>
 <body>
-
-
-<grid>
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
@@ -64,6 +54,6 @@
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002a-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002a-ref.html
index 0e6a720..a9f9a58f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002a-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002a-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid class="rows">
+<grid>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid>
+  <subgrid style="grid: none">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002a.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002a.html
index d42f619..5a6a96f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002a.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002a.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,10 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,35 +42,20 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid class="rows">
-  <item style="height: 24px;">1</item>
-  <item style="height: 40px;">2</item>
-  <item style="height: 40px;">3</item>
-  <subgrid style="height: calc(30px + 4px + 20px);">
-    <item style="height: 13px;">4a</item>
-    <item style="height: 29px;">4b</item>
-    <item style="height: 19px;">4c</item>
+<grid-lanes>
+  <item>1</item>
+  <item>2</item>
+  <item>3</item>
+  <subgrid>
+    <item>4a</item>
+    <item>4b</item>
+    <item>4c</item>
   </subgrid>
-  <item style="height: 30px;">5</item>
-</grid>
-
-</body></html>
+  <item>5</item>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002b-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002b-ref.html
index 56609cb..58d1054 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002b-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002b-ref.html
@@ -15,7 +15,6 @@
 grid {
   display: inline-grid;
   grid-template-rows: 40px 30px 20px;
-  grid-template-columns: grid-lanes;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
   border: solid;
@@ -25,7 +24,6 @@
 }
 .rows {
   grid-template-columns: 40px 30px 20px;
-  grid-template-rows: grid-lanes;
   grid-auto-flow: row;
 }
 item {
@@ -67,7 +65,7 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid class="rows">
+<grid>
   <item>1</item>
   <subgrid class="definite">
     <item>4a</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002b.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002b.html
index 6236ab3f..22e8e43 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002b.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002b.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,10 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,26 +42,11 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid class="rows">
+<grid-lanes>
   <item>1</item>
   <subgrid>
     <item>4a</item>
@@ -76,6 +56,6 @@
   <item>2</item>
   <item>3</item>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002c-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002c-ref.html
index 041e313..d309201 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002c-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002c-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid class="rows">
+<grid>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid: none / 27px 17px">
+  <subgrid style="grid: 29px 19px">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002c.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002c.html
index 518633e..89fe8c776 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002c.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002c.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,10 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -50,23 +45,11 @@
 subgrid.definite {
   grid-row-start:2;
 }
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid class="rows">
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
@@ -76,6 +59,6 @@
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002d-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002d-ref.html
index 02afb6c7..f66335d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002d-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002d-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid class="rows">
+<grid>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid class="extent" style="grid: none / 37px 24px 17px">
+  <subgrid class="extent" style="grid: 39px 28px 19px">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002d.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002d.html
index e1896e6..13b23b7a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002d.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002d.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,10 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,26 +42,14 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
 subgrid.extent {
   grid-row: auto/span 3;
 }
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid class="rows">
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
@@ -76,6 +59,6 @@
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002e-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002e-ref.html
index 5f279cb..e24e18a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002e-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002e-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid class="rows">
+<grid>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid: none / none">
+  <subgrid style="grid: none">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002e.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002e.html
index ddcdea24..07f18f3d3 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002e.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002e.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,10 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,35 +42,20 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid class="rows">
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid: none / subgrid">
+  <subgrid style="grid: subgrid / none">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002f-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002f-ref.html
index 744c44b..78bd6fea 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002f-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002f-ref.html
@@ -65,7 +65,7 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid class="rows">
+<grid>
   <item>1</item>
   <subgrid class="definite">
     <item>4a</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002f.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002f.html
index 0d0cc47..5a9d304 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002f.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002f.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,10 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,28 +42,13 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid class="rows">
+<grid-lanes>
   <item>1</item>
-  <subgrid style="grid: none / subgrid">
+  <subgrid style="grid: subgrid / none">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
@@ -76,6 +56,5 @@
   <item>2</item>
   <item>3</item>
   <item>5</item>
-</grid>
-
+</grid-lanes>
 </body></html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002g-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002g-ref.html
index cdbfd22a..250165a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002g-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002g-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid class="rows">
+<grid>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid: none / 27px 17px">
+  <subgrid style="grid: 29px 19px">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002g.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002g.html
index 3b8f9aeb..a63fbe33 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002g.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002g.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,10 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -50,23 +45,11 @@
 subgrid.definite {
   grid-row-start:2;
 }
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid class="rows">
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
@@ -76,6 +59,6 @@
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002h-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002h-ref.html
index 86df33d0..16e337c7 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002h-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002h-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid class="rows">
+<grid>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid class="extent" style="grid: none / 37px 24px 17px">
+  <subgrid class="extent" style="grid: 39px 28px 19px">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002h.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002h.html
index 038655a937..7438ac1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002h.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002h.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,10 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,26 +42,14 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
 subgrid.extent {
   grid-row: auto/span 3;
 }
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid class="rows">
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
@@ -76,6 +59,6 @@
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002i-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002i-ref.html
index 030b0e6..76bb93c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002i-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002i-ref.html
@@ -65,11 +65,11 @@
 
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
 
-<grid class="rows">
+<grid>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid: none / auto auto">
+  <subgrid style="grid: auto auto">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002i.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002i.html
index 8aa3f2e..83735a9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002i.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-lanes/tentative/subgrid/row/grid-lanes-subgrid-002i.html
@@ -14,9 +14,8 @@
   color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0;
 }
 
-grid {
+grid-lanes {
   display: inline-grid-lanes;
-  grid-lanes-direction: row;
   grid-template-rows: 40px 30px 20px;
   gap: 4px 2px;
   padding: 1px 3px 5px 7px;
@@ -24,10 +23,6 @@
   border-width: 3px 5px 1px 1px;
   background: lightgrey content-box;
 }
-.rows {
-  grid-lanes-direction: column;
-  grid-template-columns: 40px 30px 20px;
-}
 item {
   background: grey;
   width: 3ch;
@@ -47,35 +42,20 @@
   grid-gap: 6px 8px;
   background: yellow;
 }
-subgrid.definite {
-  grid-row-start:2;
-}
-subgrid.extent {
-  grid-row: auto/span 3;
-}
-.rows > subgrid.definite {
-  grid-column-start:2;
-}
-.rows > subgrid.extent {
-  grid-row: auto/span 2;
-  grid-column: auto/span 3;
-}
 </style>
 </head>
 <body>
-
 <!-- auto-placed subgrid inhibits subgridding when parent is doing grid-lanes layout ... -->
-
-<grid class="rows">
+<grid-lanes>
   <item>1</item>
   <item>2</item>
   <item>3</item>
-  <subgrid style="grid: subgrid / auto auto">
+  <subgrid style="grid: auto auto / subgrid">
     <item>4a</item>
     <item>4b</item>
     <item>4c</item>
   </subgrid>
   <item>5</item>
-</grid>
-
-</body></html>
+</grid-lanes>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-001.tentative.html b/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-001.tentative.html
deleted file mode 100644
index c9faa69..0000000
--- a/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-001.tentative.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE html>
-<link rel="help" href="https://github.com/whatwg/html/pull/9144">
-<link rel="author" href="mailto:xiaochengh@chromium.org">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<style>
-body {
-  margin: 0;
-}
-#anchor {
-  width: 100px;
-  height: 100px;
-  margin-left: 50px;
-  margin-top: 50px;
-  background: orange;
-}
-#target {
-  position: absolute;
-  left: anchor(right);
-  top: anchor(top);
-  width: 100px;
-  height: 100px;
-  background: lime;
-}
-</style>
-<div id="anchor"></div>
-<div id="target" anchor="anchor"></div>
-
-<script>
-test(() => {
-  assert_equals(target.offsetLeft, 150);
-  assert_equals(target.offsetTop, 50);
-}, 'The anchor attribute should position the target element next to its implicit anchor');
-
-test(() => {
-  assert_equals(target.anchorElement, anchor);
-}, 'The element.anchorElement IDL should reflect the element pointed to by the anchor attribute');
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-002.tentative.html b/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-002.tentative.html
deleted file mode 100644
index a1a237a..0000000
--- a/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-002.tentative.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE html>
-<link rel="help" href="https://github.com/whatwg/html/pull/9144">
-<link rel="author" href="mailto:xiaochengh@chromium.org">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<style>
-body {
-  margin: 0;
-}
-.anchor {
-  width: 100px;
-  height: 100px;
-  margin-left: 50px;
-  margin-top: 50px;
-  background: orange;
-}
-.target {
-  position: absolute;
-  left: anchor(right, 123px);
-  top: anchor(top, 456px);
-  width: 100px;
-  height: 100px;
-  background: lime;
-}
-</style>
-<div class="anchor" id="anchor1"></div>
-<div class="anchor" id="anchor2"></div>
-<div class="target" id="target1" anchor="anchor1"></div>
-<div class="target" id="target2" anchor="anchor1"></div>
-
-<script>
-test(() => {
-  document.body.offsetLeft; // Force layout
-  target1.setAttribute('anchor', 'anchor2');
-  assert_equals(target1.offsetLeft, 150);
-  assert_equals(target1.offsetTop, 200);
-
-  target1.setAttribute('anchor', 'anchor1');
-  assert_equals(target1.offsetLeft, 150);
-  assert_equals(target1.offsetTop, 50);
-}, 'Layout should be updated when anchor attribute changes to another element');
-
-test(() => {
-  document.body.offsetLeft; // Force layout
-  target2.setAttribute('anchor', 'nonexist-anchor');
-  assert_equals(target2.offsetLeft, 123);
-  assert_equals(target2.offsetTop, 456);
-}, 'Layout should be updated when anchor attribute changes to a non-existent element');
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-003-crash.tentative.html b/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-003-crash.tentative.html
deleted file mode 100644
index 207275d..0000000
--- a/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-003-crash.tentative.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<title>Tests that using the `anchor` attribute with inline containing block does not crash</title>
-<link rel="help" href="https://github.com/whatwg/html/pull/9144">
-<link rel="help" href="https://crbug.com/1486148">
-<link rel="author" href="mailto:xiaochengh@chromium.org">
-
-<style>
-.target {
-  position: absolute;
-  top: anchor(top);
-  left: anchor(right);
-}
-</style>
-
-<div id="anchor">foo</div>
-
-<span style="position: relative">
-  <div anchor="anchor2" class="target">bar</div>
-</span>
-
-<span style="position: sticky">
-  <div anchor="anchor2" class="target">bar</div>
-</span>
-
-<span style="backdrop-filter: blur(1px)">
-  <div anchor="anchor2" class="target">bar</div>
-</span>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-004.tentative.html b/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-004.tentative.html
deleted file mode 100644
index 388e7177..0000000
--- a/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-004.tentative.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<link rel=author href="mailto:masonf@chromium.org">
-<link rel="help" href="https://github.com/whatwg/html/pull/9144">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<div id=anchor1>Anchor 1</div>
-<div id=anchor2>Anchor 2</div>
-<svg id=foo anchor=anchor1></svg>
-
-<script>
-test(() => {
-  assert_equals(foo.anchorElement,anchor1,'Non-HTML elements can use the anchor attribute');
-  foo.anchorElement = anchor2;
-  assert_equals(foo.anchorElement,anchor2,'The anchorElement IDL also works for non-HTML elements');
-});
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-xml.tentative.html b/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-xml.tentative.html
deleted file mode 100644
index 6e060529..0000000
--- a/third_party/blink/web_tests/external/wpt/html/dom/elements/global-attributes/the-anchor-attribute-xml.tentative.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<link rel=author href="mailto:jarhar@chromium.org">
-<link rel="help" href="https://github.com/whatwg/html/pull/9144">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<body>
-<script>
-test(() => {
-  const xmlDoc = document.implementation.createDocument(null, 'root', null);
-  assert_equals(xmlDoc.contentType, 'application/xml');
-  const innerDoc = xmlDoc.documentElement;
-  const html = '<div id="target">target</div><div anchor="target">anchored</div>';
-  innerDoc.innerHTML = html;
-  assert_equals(innerDoc.innerHTML, html);
-  const target = innerDoc.children[0];
-  const anchored = innerDoc.children[1];
-
-  assert_equals(anchored.anchorElement, target, 'Setting the anchor attribute in XML should work.');
-
-  anchored.anchorElement = target;
-  assert_equals(anchored.anchorElement, target, 'Setting element.anchorElement in an XML document should work.');
-});
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/positional-methods-with-trusted-types.html b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/positional-methods-with-trusted-types.html
new file mode 100644
index 0000000..ef72f0f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/positional-methods-with-trusted-types.html
@@ -0,0 +1,143 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>
+  HTML partial updates - {append|prepend|before|after|replaceWith}HTML{Unafe}
+  with trusted types
+</title>
+<link rel="help" href="https://github.com/WICG/declarative-partial-updates" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/util.js"></script>
+<meta
+  http-equiv="Content-Security-Policy"
+  content="require-trusted-types-for 'script';"
+/>
+
+<body>
+  <script>
+    let createHTML = (html) => html;
+    let createParserOptions = (options) => options;
+    const default_policy = trustedTypes.createPolicy("default", {
+      createHTML: (html) => createHTML(html),
+      createParserOptions: (options) => createParserOptions(options),
+    });
+
+    function create_tests(target_type, pos, safe) {
+      const method_name = `${pos}HTML${safe ? "" : "Unsafe"}`;
+      const variant = `${target_type}.${method_name}`;
+      const prepare = (t) => {
+        t.add_cleanup(() => {
+          createHTML = (html) => html;
+          createParserOptions = (options) => options;
+        });
+        return prepare_html_partial_update(target_type, "Element", pos, t);
+      };
+
+      test(
+        (t) => {
+          const { target, ref, object } = prepare(t);
+          createHTML = (html) => {
+            if (safe) {
+              return html.replace("html", "forbidden");
+            } else {
+              return html.replace("forbidden", "html");
+            }
+          };
+          object[method_name](
+            safe ? "<span>html;</span>" : "<span>forbidden;</span>",
+          );
+          check_position(target, pos, ref);
+        },
+        `${variant} ${safe ? "does not go" : "goes"} via createHTML`,
+      );
+
+      for (const run_scripts_at_caller of [true, false]) {
+        for (const run_scripts_at_policy of [true, false]) {
+          test((t) => {
+            createParserOptions = (options) => ({
+              ...options,
+              runScripts: run_scripts_at_policy,
+            });
+
+            const { target, ref, object } = prepare(t);
+            window.did_run = false;
+            t.add_cleanup(() => {
+              delete window.did_run;
+            });
+            object[method_name](
+              "<span>html;</span><script>window.did_run = true<" + "/script>",
+              { runScripts: run_scripts_at_caller },
+            );
+            const script = target.querySelector("script");
+            assert_equals(!!script, !safe);
+            if (script) script.remove();
+            assert_equals(
+              window.did_run,
+              run_scripts_at_policy && run_scripts_at_caller && !safe,
+            );
+
+            check_position(target, pos, ref);
+          }, `Policies can disable scripts but not enable them: ${variant} (runScripts=${run_scripts_at_caller} => ${run_scripts_at_policy})`);
+        }
+      }
+
+      test((t) => {
+        createParserOptions = (options) => ({
+          ...options,
+          sanitizer: { removeElements: ["p"] },
+        });
+        const { target, ref, object } = prepare(t);
+        object[method_name]("<span>html;</span><p>forbidden</p>");
+        check_position(target, pos, ref);
+        assert_equals(target.querySelector("p"), null);
+      }, `Policy can inject sanitizer: ${variant}`);
+
+      test((t) => {
+        createParserOptions = (options) => ({
+          sanitizer: {
+            removeElements: ["span"],
+          },
+          runScripts: false,
+        });
+        window.did_run = false;
+        t.add_cleanup(() => {
+          delete window.did_run;
+        });
+        const trusted_policy = trustedTypes.createPolicy("trusted", {
+          createParserOptions: (options) => ({
+            ...options,
+            sanitizer: { removeElements: ["p"] },
+          }),
+        });
+        const { target, ref, object } = prepare(t);
+        const trusted_options = trusted_policy.createParserOptions({
+          runScripts: true,
+        });
+        assert_true(trusted_options.runScripts);
+        object[method_name](
+          "<span>html;</span><p>forbidden</p><script>window.did_run = true;<" +
+            "/script>",
+          trusted_options,
+        );
+        target.querySelector("script")?.remove();
+        check_position(target, pos, ref);
+        assert_equals(target.querySelector("p"), null);
+        assert_equals(window.did_run, !safe);
+      }, `TrustedParserOptions overrides default policy: ${variant}`);
+    }
+
+    for (const target of ["Element", "ShadowRoot"]) {
+      for (const pos of [
+        "before",
+        "after",
+        "replaceWith",
+        "append",
+        "prepend",
+      ]) {
+        for (const safe of [true, false]) {
+          create_tests(target, pos, safe);
+        }
+      }
+    }
+  </script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/positional-methods.html b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/positional-methods.html
new file mode 100644
index 0000000..375eae44
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/positional-methods.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>
+  HTML partial updates - {append|prepend|before|after|replaceWith}HTML{Unafe}
+</title>
+<link rel="help" href="https://github.com/WICG/declarative-partial-updates" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/util.js"></script>
+<body>
+  <script>
+    function create_tests(target_type, pos, ref_type, safe) {
+      const method_name = `${pos}HTML${safe ? "" : "Unsafe"}`;
+      const variant = `${ref_type}.${method_name} (${target_type})`;
+
+      function prepare(t) {
+        return prepare_html_partial_update(target_type, ref_type, pos, t);
+      }
+
+      test((t) => {
+        const { target, ref, object } = prepare(t);
+        object[method_name]("<span>html;</span>");
+        check_position(target, pos, ref);
+      }, `Position check: ${variant}`);
+
+      for (const runScripts of [true, false]) {
+        test((t) => {
+          const { target, ref, object } = prepare(t);
+          window.did_run = false;
+          t.add_cleanup(() => {
+            delete window.did_run;
+          });
+          object[method_name](
+            "<span>html;</span><script>window.did_run = true<" + "/script>",
+            { runScripts },
+          );
+          const script = target.querySelector("script");
+          assert_equals(!!script, !safe);
+          if (script) script.remove();
+          assert_equals(window.did_run, runScripts && !safe);
+
+          check_position(target, pos, ref);
+        }, `Only unsafe variants should run scripts: ${variant} (runScripts=${runScripts})`);
+      }
+
+      test((t) => {
+        const { target, ref, object } = prepare(t);
+        object[method_name]("<span>html;</span><p>forbidden</p>", {
+          sanitizer: { removeElements: ["p"] },
+        });
+        check_position(target, pos, ref);
+        assert_equals(target.querySelector("p"), null);
+      }, `Sanitizer should remove forbidden elements: ${variant}`);
+    }
+
+    for (const target of ["Element", "ShadowRoot"]) {
+      for (const pos of ["append", "prepend"]) {
+        for (const safe of [true, false]) {
+          create_tests(target, pos, "Element", safe);
+        }
+      }
+
+      for (const ref of [
+        "Element",
+        "Comment",
+        "Text",
+        "ProcessingInstruction",
+      ]) {
+        for (const pos of ["before", "after", "replaceWith"]) {
+          for (const safe of [true, false]) {
+            create_tests(target, pos, ref, safe);
+          }
+        }
+      }
+    }
+  </script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/resources/util.js b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/resources/util.js
new file mode 100644
index 0000000..54685ab
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/resources/util.js
@@ -0,0 +1,55 @@
+function prepare_html_partial_update(target_type, ref_type, pos, t) {
+  const div = document.createElement("div");
+  document.body.append(div);
+  t.add_cleanup(() => div.remove());
+  let target = div;
+  if (target_type === "ShadowRoot") {
+    const shadow_root = div.attachShadow({ mode: "open" });
+    target = shadow_root;
+  }
+
+  let ref = document.createElement("span");
+  switch (ref_type) {
+    case "Element":
+      ref.textContent = "ref;";
+      break;
+    case "Comment":
+      ref = document.createComment("ref;");
+      break;
+    case "Text":
+      ref = document.createTextNode("ref;");
+      break;
+    case "ProcessingInstruction":
+      ref = document.createProcessingInstruction("ref", "");
+      break;
+    default:
+      throw new Error("Invalid ref_type");
+  }
+  target.append(ref);
+  const object = ["append", "prepend"].includes(pos) ? target : ref;
+  return { target, ref, object };
+}
+
+
+function check_position(target, pos, ref) {
+  switch (pos) {
+    case "before":
+      assert_equals(target.firstChild.textContent, "html;");
+      assert_equals(target.firstChild.nextSibling, ref);
+      break;
+    case "prepend":
+      assert_equals(target.textContent, "html;ref;");
+      break;
+    case "after":
+      assert_equals(target.lastChild.textContent, "html;");
+      assert_equals(target.firstChild, ref);
+      break;
+    case "append":
+      assert_equals(target.textContent, "ref;html;");
+      break;
+    case "replaceWith":
+      assert_equals(target.textContent, "html;");
+      assert_equals(target.firstChild, target.lastChild);
+      break;
+  }
+}
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/stream-append-html.html b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/stream-append-html.html
new file mode 100644
index 0000000..e8e7259
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/stream-append-html.html
@@ -0,0 +1,234 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>HTML partial updates - streamAppendHTML</title>
+<link rel="help" href="https://github.com/WICG/declarative-partial-updates" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style id="style"></style>
+<p id="target"></p>
+<div id="container"></div>
+<script>
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "A";
+    const writable = placeholder.streamAppendHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamAppendHTML() returns a writable stream",
+    );
+    const response = new Response("<span>B</span>", {
+      headers: { "Content-Type": "text/html" },
+    });
+    await response.body.pipeThrough(new TextDecoderStream()).pipeTo(writable);
+    assert_equals(placeholder.textContent, "AB");
+    assert_true(response.bodyUsed);
+  }, "piping a response into streamAppendHTML()");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "<span>A</span>";
+    const writable = placeholder.streamAppendHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamAppendHTML() returns a writable stream",
+    );
+    const writer = writable.getWriter();
+    await writer.write("B");
+    await writer.close();
+    assert_equals(placeholder.textContent, "AB");
+  }, "writing a string to streamAppendHTML()");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "<span>A</span>";
+    const writable = placeholder.streamAppendHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamAppendHTML() returns a writable stream",
+    );
+    assert_equals(placeholder.textContent, "A");
+    const writer = writable.getWriter();
+    await writer.write("B");
+    await writer.close();
+    assert_equals(placeholder.textContent, "AB");
+  }, "streamAppendHTML() should append to existing content");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "<span>A</span>";
+    const writable = placeholder.streamAppendHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamAppendHTML() returns a writable stream",
+    );
+    const writer = writable.getWriter();
+    await writer.write("<span>B</span>");
+    assert_equals(placeholder.textContent, "AB");
+    await writer.close();
+  }, "streamAppendHTML() does not buffer until close()");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "Before";
+    const writable = placeholder.streamAppendHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "streamAppendHTML() returns a writable stream",
+    );
+    const writer = writable.getWriter();
+    await promise_rejects_js(t, TypeError, writer.write(Symbol("sym")));
+    assert_equals(placeholder.textContent, "Before");
+  }, "writing a Symbol to streamAppendHTML()");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "12";
+    const writable = placeholder.streamAppendHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamAppendHTML() returns a writable stream",
+    );
+    const writer = writable.getWriter();
+    await writer.write(345);
+    await writer.close();
+    assert_equals(placeholder.textContent, "12345");
+    assert_equals(placeholder.childNodes.length, 1);
+    assert_equals(placeholder.firstChild.nodeType, Node.TEXT_NODE);
+    assert_equals(placeholder.firstChild.textContent, "12345");
+  }, "writing numbers to streamAppendHTML()");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "start ";
+    const writable = placeholder.streamAppendHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamAppendHTML() returns a writable stream",
+    );
+    const writer = writable.getWriter();
+    await writer.write(null);
+    await writer.write(" ");
+    await writer.write(undefined);
+    await writer.close();
+    assert_equals(placeholder.textContent, "start null undefined");
+  }, "writing null or undefined to streamAppendHTML()");
+
+  promise_test(async (t) => {
+    const style = document.querySelector("#style");
+    const writable = style.streamAppendHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamAppendHTML() returns a writable stream",
+    );
+    const writer = await writable.getWriter();
+    await writer.write("#target { color: rgba(100, 0, 100); }");
+    await writer.close();
+    assert_equals(
+      getComputedStyle(document.querySelector("#target")).color,
+      "rgb(100, 0, 100)",
+    );
+  }, "streamAppendHTML() can stream into <style>");
+
+  promise_test(async (t) => {
+    const style = document.createElement("style");
+    style.innerHTML = "#target { color: rgba";
+    const writable = style.streamAppendHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamAppendHTML() returns a writable stream",
+    );
+    const writer = await writable.getWriter();
+    await writer.write("(100, 0, 100); }");
+    await writer.close();
+    assert_equals(
+      getComputedStyle(document.querySelector("#target")).color,
+      "rgb(100, 0, 100)",
+    );
+  }, "streamAppendHTML() can stream into a non-empty <style>");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "start ";
+    const writable = placeholder.streamAppendHTML();
+    const writer = writable.getWriter();
+    await writer.write("ABC");
+    await writer.abort("abort-reason");
+    await writer.write("DEF").catch(() => {});
+    assert_equals(placeholder.textContent, "start ABC");
+  }, "Aborting streamAppendHTML()");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "before";
+    const writer1 = placeholder.streamAppendHTML().getWriter();
+    const writer2 = placeholder.streamAppendHTML().getWriter();
+    await writer1.write("<span>A</span>");
+    await writer2.write("<span>B</span>");
+    await new Promise((resolve) => requestAnimationFrame(resolve));
+    await writer1.write("C");
+    await writer1.close();
+    await writer2.close();
+    assert_equals(placeholder.textContent, "beforeABC");
+  }, "Interleaved streamAppendHTML() writes");
+
+  promise_test(async (t) => {
+    const element = document.createElement("div");
+    document.body.append(element);
+    window.did_eval_script = false;
+    const writer = element.streamAppendHTML({ runScripts: true }).getWriter();
+    assert_false(window.did_eval_script);
+    await writer.write("<script>window.did_eval_script = true;");
+    assert_false(window.did_eval_script);
+    await writer.write("<");
+    assert_false(window.did_eval_script);
+    await writer.write("/script>");
+    assert_false(window.did_eval_script);
+  }, "streamAppendHTML should not execute scripts when connected");
+
+  promise_test(async (t) => {
+    const element = document.createElement("div");
+    element.innerHTML = "<p>before;</p>";
+    document.body.append(element);
+    const writer = element
+      .streamAppendHTML({ sanitizer: { removeElements: ["p"] } })
+      .getWriter();
+    await writer.write("<p>forbidden</p>");
+    await writer.write("<span>allowed</span>");
+    await writer.close();
+    assert_equals(element.textContent, "before;allowed");
+  }, "streamAppendHTML should pass sanitizer options");
+
+  promise_test(async (t) => {
+    const element = document.createElement("div");
+    const shadow = element.attachShadow({mode: "open"});
+    shadow.innerHTML = "<p>before;</p>";
+    document.body.append(element);
+    const writer = shadow
+      .streamAppendHTML({ sanitizer: { removeElements: ["p"] } })
+      .getWriter();
+    await writer.write("<p>forbidden</p>");
+    await writer.write("<span>allowed</span>");
+    await writer.close();
+    assert_equals(shadow.textContent, "before;allowed");
+
+  }, "streamAppendHTML on ShadowRoot");
+  promise_test(async (t) => {
+    const element = document.createElement("div");
+    element.innerHTML = "before;";
+    document.body.append(element);
+    const writer = element.streamAppendHTML().getWriter();
+    await writer.write("<script id=forbidden><" + "/script><span id=after>after</span>");
+    await writer.close();
+    assert_equals(element.querySelector("script"), null);
+    assert_equals(element.textContent, "before;after");
+  }, "streamAppendHTML uses safe sanitizer");
+
+  promise_test(async (t) => {
+    const element = document.createElement("div");
+    const shadow = element.attachShadow({mode: "open"});
+    document.body.append(element);
+    const writer = shadow.streamAppendHTML().getWriter();
+    await writer.write("<script id=forbidden<" + "/script>");
+    await writer.close();
+    assert_equals(shadow.querySelector("script"), null);
+  }, "streamAppendHTML on ShadowRoot uses safe sanitizer");</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/stream-html-custom-element.html b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/stream-html-custom-element.html
new file mode 100644
index 0000000..5345c2f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/stream-html-custom-element.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>HTML partial updates - streamHTMLUnsafe invokes CE reactions</title>
+<link rel="help" href="https://github.com/WICG/declarative-partial-updates" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div id="container"></div>
+<script>
+for (const method of ["streamHTMLUnsafe", "streamAppendHTMLUnsafe"]) {
+  promise_test(async (t) => {
+    const container = document.getElementById("container");
+    const name = "element-for-" + method.toLowerCase();
+    t.add_cleanup(() => container.replaceChildren());
+    customElements.define(
+      name,
+      class extends HTMLElement {
+        constructor() {
+          super();
+          this.append("Defined;");
+        }
+
+        connectedCallback() {
+          this.append("Connected");
+        }
+      },
+    );
+    const writer = container[method]().getWriter();
+    await writer.write(`<${name}></${name}>`);
+    await writer.close();
+    assert_equals(container.textContent, "Defined;Connected");
+  }, `${method} should trigger CE reactions`);
+
+  promise_test(async (t) => {
+    const container = document.getElementById("container");
+    t.add_cleanup(() => container.replaceChildren());
+    const scoped = new CustomElementRegistry();
+    scoped.define(
+      "scoped-element",
+      class extends HTMLElement {
+        constructor() {
+          super();
+          this.append("Scoped;");
+        }
+
+        connectedCallback() {
+          this.append("Connected");
+        }
+      },
+    );
+    const inner = document.createElement("div", {
+      customElementRegistry: scoped,
+    });
+    container.append(inner);
+    const writer = inner[method]().getWriter();
+    await writer.write("<scoped-element></scoped-element>");
+    await writer.close();
+    assert_equals(inner.textContent, "Scoped;Connected");
+  }, `${method} should use scoped custom element registry`);
+}
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/stream-html-run-scripts-option.html b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/stream-html-run-scripts-option.html
index df81dc5..f40b1cb 100644
--- a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/stream-html-run-scripts-option.html
+++ b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/stream-html-run-scripts-option.html
@@ -28,7 +28,6 @@
         assert_false(window.did_run);
     }, `element.${method} with runScripts: false`);
 
-
     promise_test(async t => {
         const placeholder = document.getElementById("placeholder");
         const element = document.createElement("div");
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/stream-html.html b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/stream-html.html
new file mode 100644
index 0000000..4f750a1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/stream-html.html
@@ -0,0 +1,216 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>HTML partial updates - streamHTML</title>
+<link rel="help" href="https://github.com/WICG/declarative-partial-updates" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style id="style"></style>
+<p id="target"></p>
+<div id="container"></div>
+<script>
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "A";
+    const writable = placeholder.streamHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamHTML() returns a writable stream",
+    );
+    const response = new Response("<span>B</span>", {
+      headers: { "Content-Type": "text/html" },
+    });
+    await response.body.pipeThrough(new TextDecoderStream()).pipeTo(writable);
+    assert_equals(placeholder.textContent, "B");
+    assert_true(response.bodyUsed);
+  }, "piping a response into streamHTML()");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "<span>A</span>";
+    const writable = placeholder.streamHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamHTML() returns a writable stream",
+    );
+    const writer = writable.getWriter();
+    await writer.write("B");
+    await writer.close();
+    assert_equals(placeholder.textContent, "B");
+  }, "writing a string to streamHTML()");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "<span>A</span>";
+    const writable = placeholder.streamHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamHTML() returns a writable stream",
+    );
+    assert_equals(placeholder.textContent, "");
+    const writer = writable.getWriter();
+    await writer.write("B");
+    await writer.close();
+    assert_equals(placeholder.textContent, "B");
+  }, "streamHTML() should remove existing content immediately");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "<span>A</span>";
+    const writable = placeholder.streamHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamHTML() returns a writable stream",
+    );
+    const writer = writable.getWriter();
+    await writer.write("<span>B</span>");
+    assert_equals(placeholder.textContent, "B");
+    await writer.close();
+  }, "streamHTML() does not buffer until close()");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "Before";
+    const writable = placeholder.streamHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "streamHTML() returns a writable stream",
+    );
+    const writer = writable.getWriter();
+    await promise_rejects_js(t, TypeError, writer.write(Symbol("sym")));
+    assert_equals(placeholder.textContent, "");
+  }, "writing a Symbol to streamHTML()");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "12";
+    const writable = placeholder.streamHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamHTML() returns a writable stream",
+    );
+    const writer = writable.getWriter();
+    await writer.write(345);
+    await writer.close();
+    assert_equals(placeholder.textContent, "345");
+    assert_equals(placeholder.childNodes.length, 1);
+    assert_equals(placeholder.firstChild.nodeType, Node.TEXT_NODE);
+    assert_equals(placeholder.firstChild.textContent, "345");
+  }, "writing numbers to streamHTML()");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "start ";
+    const writable = placeholder.streamHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamHTML() returns a writable stream",
+    );
+    const writer = writable.getWriter();
+    await writer.write(null);
+    await writer.write(" ");
+    await writer.write(undefined);
+    await writer.close();
+    assert_equals(placeholder.textContent, "null undefined");
+  }, "writing null or undefined to streamHTML()");
+
+  promise_test(async (t) => {
+    const style = document.querySelector("#style");
+    const writable = style.streamHTML();
+    assert_true(
+      writable instanceof WritableStream,
+      "node.streamHTML() returns a writable stream",
+    );
+    const writer = await writable.getWriter();
+    await writer.write("#target { color: rgba(100, 0, 100); }");
+    await writer.close();
+    assert_equals(
+      getComputedStyle(document.querySelector("#target")).color,
+      "rgb(100, 0, 100)",
+    );
+  }, "streamHTML() can stream into <style>");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "start ";
+    const writable = placeholder.streamHTML();
+    const writer = writable.getWriter();
+    await writer.write("ABC");
+    await writer.abort("abort-reason");
+    await writer.write("DEF").catch(() => {});
+    assert_equals(placeholder.textContent, "ABC");
+  }, "Aborting streamHTML()");
+
+  promise_test(async (t) => {
+    const placeholder = document.createElement("div");
+    placeholder.innerHTML = "before";
+    const writer1 = placeholder.streamHTML().getWriter();
+    const writer2 = placeholder.streamHTML().getWriter();
+    await writer1.write("<span>A</span>");
+    await writer2.write("<span>B</span>");
+    await new Promise((resolve) => requestAnimationFrame(resolve));
+    await writer1.write("C");
+    await writer1.close();
+    await writer2.close();
+    assert_equals(placeholder.textContent, "ABC");
+  }, "Interleaved streamHTML() writes");
+
+  promise_test(async (t) => {
+    const element = document.createElement("div");
+    document.body.append(element);
+    window.did_eval_script = false;
+    const writer = element.streamHTML({ runScripts: true }).getWriter();
+    assert_false(window.did_eval_script);
+    await writer.write("<script>window.did_eval_script = true;");
+    assert_false(window.did_eval_script);
+    await writer.write("<");
+    assert_false(window.did_eval_script);
+    await writer.write("/script>");
+    assert_false(window.did_eval_script);
+  }, "streamHTML should not execute scripts when connected");
+
+  promise_test(async (t) => {
+    const element = document.createElement("div");
+    element.innerHTML = "<p>before;</p>";
+    document.body.append(element);
+    const writer = element
+      .streamHTML({ sanitizer: { removeElements: ["p"] } })
+      .getWriter();
+    await writer.write("<p>forbidden</p>");
+    await writer.write("<span>allowed</span>");
+    await writer.close();
+    assert_equals(element.textContent, "allowed");
+  }, "streamHTML should pass sanitizer options");
+
+  promise_test(async (t) => {
+    const element = document.createElement("div");
+    document.body.append(element);
+    const writer = element.streamHTML().getWriter();
+    await writer.write("<script id=forbidden<" + "/script>");
+    await writer.close();
+    assert_equals(element.querySelector("script"), null);
+  }, "streamHTML uses safe sanitizer");
+
+  promise_test(async (t) => {
+    const element = document.createElement("div");
+    const shadow = element.attachShadow({mode: "open"});
+    shadow.innerHTML = "<p>before;</p>";
+    document.body.append(element);
+    const writer = shadow
+      .streamHTML({ sanitizer: { removeElements: ["p"] } })
+      .getWriter();
+    await writer.write("<p>forbidden</p>");
+    await writer.write("<span>allowed</span>");
+    await writer.close();
+    assert_equals(shadow.textContent, "allowed");
+  }, "streamHTML on ShadowRoot");
+
+  promise_test(async (t) => {
+    const element = document.createElement("div");
+    const shadow = element.attachShadow({mode: "open"});
+    document.body.append(element);
+    const writer = shadow.streamHTML().getWriter();
+    await writer.write("<script id=forbidden<" + "/script>");
+    await writer.close();
+    assert_equals(shadow.querySelector("script"), null);
+  }, "streamHTML on ShadowRoot uses safe sanitizer");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/horizontal/rtl-inline-only.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/horizontal/rtl-inline-only.html
new file mode 100644
index 0000000..030f0a0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/horizontal/rtl-inline-only.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - RTL with inline-only axis respects reversed arrow keys.</title>
+<meta name="assert" content="In an RTL focusgroup restricted to inline axis, ArrowLeft moves forward and ArrowRight moves backward. ArrowUp/ArrowDown should not move focus since the block axis is not supported.">
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/shadow-dom/focus-navigation/resources/focus-utils.js"></script>
+<script src="../../../resources/focusgroup-utils.js"></script>
+
+<div dir="rtl" focusgroup="toolbar inline">
+  <span id=item1 tabindex=0>item1</span>
+  <span id=item2 tabindex=0>item2</span>
+  <span id=item3 tabindex=0>item3</span>
+</div>
+
+<script>
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+
+    // ArrowLeft is forward inline in RTL.
+    await focusAndKeyPress(item1, kArrowLeft);
+    assert_equals(document.activeElement, item2,
+      "ArrowLeft should move forward inline in RTL inline-only focusgroup");
+  }, "ArrowLeft moves forward in RTL inline-only focusgroup.");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+
+    // ArrowRight is backward inline in RTL.
+    await focusAndKeyPress(item2, kArrowRight);
+    assert_equals(document.activeElement, item1,
+      "ArrowRight should move backward inline in RTL inline-only focusgroup");
+  }, "ArrowRight moves backward in RTL inline-only focusgroup.");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+
+    // Block axis keys should not move focus in an inline-only focusgroup.
+    await focusAndKeyPress(item1, kArrowDown);
+    assert_equals(document.activeElement, item1,
+      "ArrowDown should not move focus in inline-only focusgroup");
+
+    await focusAndKeyPress(item1, kArrowUp);
+    assert_equals(document.activeElement, item1,
+      "ArrowUp should not move focus in inline-only focusgroup");
+  }, "ArrowDown and ArrowUp do not move focus in RTL inline-only focusgroup.");
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/mixed-ltr-rtl-visual-order.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/mixed-ltr-rtl-visual-order.html
new file mode 100644
index 0000000..cce2ca8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/mixed-ltr-rtl-visual-order.html
@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - Arrow keys follow the focused element's writing direction.</title>
+<meta name="assert" content="In a focusgroup with mixed writing directions, arrow keys follow the focused element's inherited writing direction. An RTL item uses ArrowLeft for forward and ArrowRight for backward, even inside an LTR focusgroup container, and vice versa.">
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/shadow-dom/focus-navigation/resources/focus-utils.js"></script>
+<script src="../../resources/focusgroup-utils.js"></script>
+
+<!-- LTR container with items 1-2 inside an RTL wrapper.
+     item1/item2 inherit dir="rtl" → ArrowLeft is forward for them.
+     item3-5 are LTR → ArrowRight is forward for them. -->
+<div id=ltr-group focusgroup="toolbar">
+  <div dir="rtl">
+    <span id=item1 tabindex=0>One</span>
+    <span id=item2 tabindex=0>Two</span>
+  </div>
+  <span id=item3 tabindex=0>Three</span>
+  <span id=item4 tabindex=0>Four</span>
+  <span id=item5 tabindex=0>Five</span>
+</div>
+
+<!-- RTL container with items r2-r3 inside an LTR wrapper.
+     r1 inherits dir="rtl" → ArrowLeft is forward.
+     r2/r3 inherit dir="ltr" → ArrowRight is forward for them. -->
+<div id=rtl-group dir="rtl" focusgroup="toolbar">
+  <span id=r1 tabindex=0>One</span>
+  <div dir="ltr">
+    <span id=r2 tabindex=0>Two</span>
+    <span id=r3 tabindex=0>Three</span>
+  </div>
+</div>
+
+<script>
+
+  // --- LTR container with RTL wrapper ---
+  // item1 and item2 inherit RTL, so ArrowLeft is their forward key.
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+
+    // item1 is RTL: ArrowLeft = forward inline.
+    await focusAndKeyPress(item1, kArrowLeft);
+    assert_equals(document.activeElement, item2,
+      "ArrowLeft should move forward from RTL item1");
+  }, "LTR container: ArrowLeft (forward in RTL) from item1 moves to item2.");
+
+  promise_test(async t => {
+    var item2 = document.getElementById("item2");
+    var item3 = document.getElementById("item3");
+
+    // item2 is RTL: ArrowLeft = forward inline, crosses into LTR sibling.
+    await focusAndKeyPress(item2, kArrowLeft);
+    assert_equals(document.activeElement, item3,
+      "ArrowLeft should move forward from RTL item2 into LTR item3");
+  }, "LTR container: ArrowLeft (forward in RTL) from item2 crosses to LTR item3.");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+
+    // item2 is RTL: ArrowRight = backward inline.
+    await focusAndKeyPress(item2, kArrowRight);
+    assert_equals(document.activeElement, item1,
+      "ArrowRight should move backward from RTL item2");
+  }, "LTR container: ArrowRight (backward in RTL) from item2 moves to item1.");
+
+  // item3-5 are LTR: ArrowRight = forward, ArrowLeft = backward.
+
+  promise_test(async t => {
+    var item3 = document.getElementById("item3");
+    var item4 = document.getElementById("item4");
+
+    await focusAndKeyPress(item3, kArrowRight);
+    assert_equals(document.activeElement, item4,
+      "ArrowRight should move forward from LTR item3");
+  }, "LTR container: ArrowRight from LTR item3 moves to item4.");
+
+  promise_test(async t => {
+    var item4 = document.getElementById("item4");
+    var item5 = document.getElementById("item5");
+
+    await focusAndKeyPress(item4, kArrowRight);
+    assert_equals(document.activeElement, item5,
+      "ArrowRight should move forward from LTR item4");
+  }, "LTR container: ArrowRight from LTR item4 moves to item5.");
+
+  promise_test(async t => {
+    var item4 = document.getElementById("item4");
+    var item5 = document.getElementById("item5");
+
+    await focusAndKeyPress(item5, kArrowLeft);
+    assert_equals(document.activeElement, item4,
+      "ArrowLeft should move backward from LTR item5");
+  }, "LTR container: ArrowLeft from LTR item5 moves to item4.");
+
+  promise_test(async t => {
+    var item2 = document.getElementById("item2");
+    var item3 = document.getElementById("item3");
+
+    // item3 is LTR: ArrowLeft = backward, crosses back into RTL wrapper.
+    await focusAndKeyPress(item3, kArrowLeft);
+    assert_equals(document.activeElement, item2,
+      "ArrowLeft should move backward from LTR item3 into RTL item2");
+  }, "LTR container: ArrowLeft from LTR item3 crosses back to RTL item2.");
+
+  // --- RTL container with LTR wrapper ---
+  // r1 inherits RTL: ArrowLeft = forward. r2/r3 inherit LTR: ArrowRight = forward.
+
+  promise_test(async t => {
+    var r1 = document.getElementById("r1");
+    var r2 = document.getElementById("r2");
+
+    // r1 is RTL: ArrowLeft = forward inline.
+    await focusAndKeyPress(r1, kArrowLeft);
+    assert_equals(document.activeElement, r2,
+      "ArrowLeft should move forward from RTL r1 into LTR wrapper");
+  }, "RTL container: ArrowLeft (forward in RTL) from r1 moves to LTR r2.");
+
+  promise_test(async t => {
+    var r2 = document.getElementById("r2");
+    var r3 = document.getElementById("r3");
+
+    // r2 is LTR: ArrowRight = forward inline.
+    await focusAndKeyPress(r2, kArrowRight);
+    assert_equals(document.activeElement, r3,
+      "ArrowRight should move forward from LTR r2");
+  }, "RTL container: ArrowRight (forward in LTR) from r2 moves to r3.");
+
+  promise_test(async t => {
+    var r1 = document.getElementById("r1");
+    var r2 = document.getElementById("r2");
+
+    // r2 is LTR: ArrowLeft = backward inline.
+    await focusAndKeyPress(r2, kArrowLeft);
+    assert_equals(document.activeElement, r1,
+      "ArrowLeft should move backward from LTR r2 to RTL r1");
+  }, "RTL container: ArrowLeft (backward in LTR) from r2 moves to r1.");
+
+  promise_test(async t => {
+    var r2 = document.getElementById("r2");
+    var r3 = document.getElementById("r3");
+
+    // r3 is LTR: ArrowLeft = backward inline.
+    await focusAndKeyPress(r3, kArrowLeft);
+    assert_equals(document.activeElement, r2,
+      "ArrowLeft should move backward from LTR r3");
+  }, "RTL container: ArrowLeft (backward in LTR) from r3 moves to r2.");
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/rtl-direction-reverses-inline.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/rtl-direction-reverses-inline.html
new file mode 100644
index 0000000..8d09334
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/rtl-direction-reverses-inline.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - In RTL, ArrowLeft moves focus forward inline.</title>
+<meta name="assert" content="In an RTL focusgroup, the ArrowLeft key should move focus forward (inline-end) and ArrowRight should move focus backward (inline-start), reversing the LTR default.">
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/shadow-dom/focus-navigation/resources/focus-utils.js"></script>
+<script src="../../resources/focusgroup-utils.js"></script>
+
+<div dir="rtl" focusgroup="toolbar">
+  <span id=item1 tabindex=0>item1</span>
+  <span id=item2 tabindex=0>item2</span>
+  <span id=item3 tabindex=0>item3</span>
+</div>
+
+<script>
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+
+    // In RTL, ArrowLeft is forward inline (towards inline-end).
+    await focusAndKeyPress(item1, kArrowLeft);
+    assert_equals(document.activeElement, item2,
+      "ArrowLeft should move forward inline in RTL");
+  }, "ArrowLeft moves focus to the next item in an RTL focusgroup.");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+
+    // In RTL, ArrowRight is backward inline (towards inline-start).
+    await focusAndKeyPress(item2, kArrowRight);
+    assert_equals(document.activeElement, item1,
+      "ArrowRight should move backward inline in RTL");
+  }, "ArrowRight moves focus to the previous item in an RTL focusgroup.");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+
+    // ArrowDown should still move forward (block axis is unaffected by RTL).
+    await focusAndKeyPress(item1, kArrowDown);
+    assert_equals(document.activeElement, item2,
+      "ArrowDown should move forward block in RTL (unchanged)");
+  }, "ArrowDown moves focus forward in an RTL focusgroup (block axis unaffected).");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+
+    // ArrowUp should still move backward (block axis is unaffected by RTL).
+    await focusAndKeyPress(item2, kArrowUp);
+    assert_equals(document.activeElement, item1,
+      "ArrowUp should move backward block in RTL (unchanged)");
+  }, "ArrowUp moves focus backward in an RTL focusgroup (block axis unaffected).");
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/rtl-wraps-correctly.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/rtl-wraps-correctly.html
new file mode 100644
index 0000000..4fcc7ae4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/rtl-wraps-correctly.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - RTL wrapping respects reversed inline direction.</title>
+<meta name="assert" content="In an RTL focusgroup with wrap, ArrowLeft at the last item should wrap to the first, and ArrowRight at the first item should wrap to the last.">
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/shadow-dom/focus-navigation/resources/focus-utils.js"></script>
+<script src="../../resources/focusgroup-utils.js"></script>
+
+<div dir="rtl" focusgroup="toolbar wrap">
+  <span id=item1 tabindex=0>item1</span>
+  <span id=item2 tabindex=0>item2</span>
+  <span id=item3 tabindex=0>item3</span>
+</div>
+
+<script>
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item3 = document.getElementById("item3");
+
+    // ArrowLeft wraps forward: from last item should wrap to first.
+    await focusAndKeyPress(item3, kArrowLeft);
+    assert_equals(document.activeElement, item1,
+      "ArrowLeft from last item should wrap to first in RTL");
+  }, "ArrowLeft at last item wraps to first item in RTL focusgroup.");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item3 = document.getElementById("item3");
+
+    // ArrowRight wraps backward: from first item should wrap to last.
+    await focusAndKeyPress(item1, kArrowRight);
+    assert_equals(document.activeElement, item3,
+      "ArrowRight from first item should wrap to last in RTL");
+  }, "ArrowRight at first item wraps to last item in RTL focusgroup.");
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/vertical-writing-mode.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/vertical-writing-mode.html
new file mode 100644
index 0000000..0b25ea9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/vertical-writing-mode.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - Vertical writing-mode swaps inline and block axes.</title>
+<meta name="assert" content="In a vertical-rl writing mode, the inline axis runs vertically and the block axis runs horizontally. ArrowDown/Up should navigate inline; ArrowLeft/Right should navigate block.">
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/shadow-dom/focus-navigation/resources/focus-utils.js"></script>
+<script src="../../resources/focusgroup-utils.js"></script>
+
+<!-- In vertical-rl, inline direction runs top-to-bottom and block direction
+     runs right-to-left. An inline-only focusgroup should respond to
+     ArrowDown/ArrowUp but not ArrowLeft/ArrowRight. -->
+<div style="writing-mode: vertical-rl" focusgroup="toolbar inline">
+  <span id=item1 tabindex=0>item1</span>
+  <span id=item2 tabindex=0>item2</span>
+  <span id=item3 tabindex=0>item3</span>
+</div>
+
+<!-- Both-axes focusgroup (no axis restriction) for testing all four keys. -->
+<div id=both style="writing-mode: vertical-rl" focusgroup="toolbar">
+  <span id=b1 tabindex=0>b1</span>
+  <span id=b2 tabindex=0>b2</span>
+  <span id=b3 tabindex=0>b3</span>
+</div>
+
+<script>
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+
+    // ArrowDown is forward inline in vertical-rl.
+    await focusAndKeyPress(item1, kArrowDown);
+    assert_equals(document.activeElement, item2,
+      "ArrowDown should move forward inline in vertical-rl");
+  }, "ArrowDown moves forward inline in vertical-rl inline-only focusgroup.");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+
+    // ArrowUp is backward inline in vertical-rl.
+    await focusAndKeyPress(item2, kArrowUp);
+    assert_equals(document.activeElement, item1,
+      "ArrowUp should move backward inline in vertical-rl");
+  }, "ArrowUp moves backward inline in vertical-rl inline-only focusgroup.");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+
+    // ArrowLeft and ArrowRight are block-axis in vertical-rl; should not
+    // move focus in an inline-only focusgroup.
+    await focusAndKeyPress(item1, kArrowLeft);
+    assert_equals(document.activeElement, item1,
+      "ArrowLeft (block) should not move focus in inline-only focusgroup");
+
+    await focusAndKeyPress(item1, kArrowRight);
+    assert_equals(document.activeElement, item1,
+      "ArrowRight (block) should not move focus in inline-only focusgroup");
+  }, "ArrowLeft/ArrowRight do not move focus in vertical-rl inline-only focusgroup.");
+
+  promise_test(async t => {
+    var b1 = document.getElementById("b1");
+    var b2 = document.getElementById("b2");
+
+    // In both-axes vertical-rl, ArrowDown is forward inline.
+    await focusAndKeyPress(b1, kArrowDown);
+    assert_equals(document.activeElement, b2,
+      "ArrowDown should move forward in both-axes vertical-rl focusgroup");
+  }, "ArrowDown moves forward in both-axes vertical-rl focusgroup.");
+
+  promise_test(async t => {
+    var b1 = document.getElementById("b1");
+    var b2 = document.getElementById("b2");
+
+    // In both-axes vertical-rl, ArrowLeft is forward block.
+    await focusAndKeyPress(b1, kArrowLeft);
+    assert_equals(document.activeElement, b2,
+      "ArrowLeft should move forward in both-axes vertical-rl focusgroup");
+  }, "ArrowLeft moves forward (block) in both-axes vertical-rl focusgroup.");
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select-multiple-popup/select-multiple-popup-appearance-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select-multiple-popup/select-multiple-popup-appearance-ref.html
index 233ddbcc..6d773f5 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select-multiple-popup/select-multiple-popup-appearance-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select-multiple-popup/select-multiple-popup-appearance-ref.html
@@ -1,15 +1,17 @@
 <!DOCTYPE html>
 <link rel=stylesheet href="../customizable-select/resources/customizable-select-styles.css">
 
-<div class=customizable-select-button popovertarget=popover id=button>
+<button class=customizable-select-button popovertarget=popover id=button>
   <span class=customizable-select-selectedcontent>2 selected</span>
-</div>
-<div id=popover popover=auto anchor=button class=customizable-select-popover>
+</button>
+<div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">one</div>
   <div class="customizable-select-option selected">two</div>
   <div class=customizable-select-option>three</div>
 </div>
 
 <script>
-document.getElementById('popover').showPopover();
+const button = document.getElementById('button');
+const popover = document.getElementById('popover');
+popover.showPopover({source: button});
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/resources/customizable-select-styles.css b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/resources/customizable-select-styles.css
index 90ecced..04a9715 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/resources/customizable-select-styles.css
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/resources/customizable-select-styles.css
@@ -52,6 +52,7 @@
 
 .customizable-select-button {
   color: inherit;
+  font: inherit;
   background-color: transparent;
   appearance: none;
   padding-block: 0.25em;
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-active-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-active-ref.html
index 65742df..b6b93cd8 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-active-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-active-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <link rel=stylesheet href="resources/customizable-select-styles.css">
 
-<div class="customizable-select-button active" popovertarget=popover id=button>
+<button class="customizable-select-button active" popovertarget=popover id=button>
   <span class=customizable-select-selectedoption>option</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">option</div>
 </div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-button-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-button-ref.html
index db1036a..d7ad9664 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-button-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-button-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <link rel=stylesheet href="resources/customizable-select-styles.css">
 
-<div class=customizable-select-button popovertarget=popover id=button>
+<button class=customizable-select-button popovertarget=popover id=button>
   <span class=customizable-select-selectedcontent>one</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">one</div>
   <div class=customizable-select-option>two</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-dark-mode-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-dark-mode-ref.html
index 22fd6f6a..11a8ea3 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-dark-mode-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-dark-mode-ref.html
@@ -7,9 +7,9 @@
 }
 </style>
 
-<div class=customizable-select-button popovertarget=popover id=button>
+<button class=customizable-select-button popovertarget=popover id=button>
   <span class=customizable-select-selectedcontent>one</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">one</div>
   <div class=customizable-select-option>two</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-disabled-option-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-disabled-option-ref.html
index 576081c..dd7f46a5 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-disabled-option-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-disabled-option-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <link rel=stylesheet href="resources/customizable-select-styles.css">
 
-<div class=customizable-select-button popovertarget=popover id=button>
+<button class=customizable-select-button popovertarget=popover id=button>
   <span class=customizable-select-selectedcontent>option</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">option</div>
   <div class="customizable-select-option disabled">disabled option</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-font-inheriting-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-font-inheriting-ref.html
index e6a6a4e..0bb3fa95 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-font-inheriting-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-font-inheriting-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <link rel=stylesheet href="resources/customizable-select-styles.css">
 
-<div class="customizable-select-button open" popovertarget=popover id=button>
+<button class="customizable-select-button open" popovertarget=popover id=button>
   <span class=customizable-select-selectedcontent>one</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">one</div>
   <div class=customizable-select-option>two</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-optgroup-legend-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-optgroup-legend-ref.html
index dafb70bc..52c302d6 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-optgroup-legend-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-optgroup-legend-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <link rel=stylesheet href="resources/customizable-select-styles.css">
 
-<div class=customizable-select-button popovertarget=popover id=button>
+<button class=customizable-select-button popovertarget=popover id=button>
   <span class=customizable-select-selectedcontent>one</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">one</div>
   <div class=customizable-select-optgroup>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-optgroup-rendering-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-optgroup-rendering-ref.html
index a182a66..2be24c8 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-optgroup-rendering-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-optgroup-rendering-ref.html
@@ -7,9 +7,9 @@
 }
 </style>
 
-<div class=customizable-select-button id=button>
+<button class=customizable-select-button id=button>
   <span class=customizable-select-selectedcontent>one</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">one</div>
   <div class=customizable-select-optgroup>
@@ -25,4 +25,3 @@
 <script>
 document.getElementById('popover').showPopover({ source: button });
 </script>
-
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-picker-select-border-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-picker-select-border-ref.html
index 5aa2510d..dc784555 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-picker-select-border-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-picker-select-border-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <link rel=stylesheet href="resources/customizable-select-styles.css">
 
-<div class=customizable-select-button id=button>
+<button class=customizable-select-button id=button>
   <span class=customizable-select-selectedcontent>option</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">option</div>
 </div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-switching-invalidation-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-switching-invalidation-ref.html
index 6db21ef..01e290b 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-switching-invalidation-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-switching-invalidation-ref.html
@@ -7,9 +7,9 @@
 }
 </style>
 
-<div class=customizable-select-button popovertarget=popover id=button>
+<button class=customizable-select-button popovertarget=popover id=button>
   <span class=customizable-select-selectedoption>button</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">
     <span class=blue>option</span> one
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-writing-mode-vertical-lr-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-writing-mode-vertical-lr-ref.html
index 36ec7797..b9a99c58 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-writing-mode-vertical-lr-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-writing-mode-vertical-lr-ref.html
@@ -7,9 +7,9 @@
 }
 </style>
 
-<div class=customizable-select-button id=button>
+<button class=customizable-select-button id=button>
   <div class=customizable-select-selectedcontent>one</div>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">one</div>
   <div class=customizable-select-option>two</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-writing-mode-vertical-rl-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-writing-mode-vertical-rl-ref.html
index 1bdabcc..1f835b8 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-writing-mode-vertical-rl-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-writing-mode-vertical-rl-ref.html
@@ -7,9 +7,9 @@
 }
 </style>
 
-<div class=customizable-select-button popovertarget=popover id=button>
+<button class=customizable-select-button popovertarget=popover id=button>
   <span class=customizable-select-selectedcontent>one</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">one</div>
   <div class=customizable-select-option>two</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-font-size-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-font-size-ref.html
index 730a2cb..58570c6 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-font-size-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-font-size-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <link rel=stylesheet href="resources/customizable-select-styles.css">
-<div class=customizable-select-button popovertarget=popover id=button>
+<button class=customizable-select-button>
   <span class=customizable-select-selectedcontent>option</span>
-</div>
+</button>
 
 <style>
-  div {
+  button.customizable-select-button {
     font-size: 48px;
   }
 </style>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-open-invalidation-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-open-invalidation-ref.html
index 22625a7..7383312 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-open-invalidation-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-open-invalidation-ref.html
@@ -7,9 +7,9 @@
 }
 </style>
 
-<div class=customizable-select-button popovertarget=popover id=button>
+<button class=customizable-select-button popovertarget=popover id=button>
   <span class=customizable-select-selectedoption>button</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div tabindex=0 class="customizable-select-option selected">one</div>
   <div class=customizable-select-option>two</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-option-images-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-option-images-ref.html
index 49e8b30b..436d3a06 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-option-images-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-option-images-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <link rel=stylesheet href="resources/customizable-select-styles.css">
 
-<div class=customizable-select-button popovertarget=popover id=button>
+<button class=customizable-select-button popovertarget=popover id=button>
   <span class=customizable-select-selectedoption>button</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div tabindex=0 class="customizable-select-option selected"><img alt="" src="/images/green-16x16.png">green-16x16</div>
   <div tabindex=0 class=customizable-select-option><img alt="" src="/images/red-16x16.png">red-16x16</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-popover-exit-animation-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-popover-exit-animation-ref.html
index 0359fd6..6ce52054 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-popover-exit-animation-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-popover-exit-animation-ref.html
@@ -2,9 +2,9 @@
 <link rel=stylesheet href="resources/customizable-select-styles.css">
 
 <div>hover target</div>
-<div class=customizable-select-button popovertarget=popover id=button>
+<button class=customizable-select-button popovertarget=popover id=button>
   <span class=customizable-select-selectedcontent>option</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">option</div>
 </div>
@@ -12,4 +12,3 @@
 <script>
 document.getElementById('popover').showPopover({ source: button });
 </script>
-
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-second-child-button-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-second-child-button-ref.html
index d1fdd539..3782d17 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-second-child-button-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-second-child-button-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <link rel=stylesheet href="resources/customizable-select-styles.css">
 
-<div class=customizable-select-button popovertarget=popover id=button>
+<button class=customizable-select-button popovertarget=popover id=button>
   <span class=customizable-select-selectedcontent>option</span>
-</div>
+</button>
 <div id=popover popover=auto class=customizable-select-popover>
   <div class="customizable-select-option selected">option</div>
   <button>button</button>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-change-display.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-change-display.tentative.html
deleted file mode 100644
index 4312a156..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-change-display.tentative.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<link rel=author href="mailto:xiaochengh@chromium.org">
-<link rel=help href="https://open-ui.org/components/popover.research.explainer">
-<link rel=help href="https://html.spec.whatwg.org/multipage/popover.html">
-<link rel=match href="popover-anchor-change-display-ref.html">
-<script src="resources/popover-utils.js"></script>
-
-<p>There should be a green box attached to the right side of each orange box.</p>
-
-<div class=ex>
-  <div class=anchor id=anchor1></div>
-  <div id=popover1 popover=manual defaultopen></div>
-</div>
-
-<div class=ex>
-  <div class=anchor id=will-be-anchor2></div>
-  <div id=popover2 popover=manual anchor=anchor2 defaultopen></div>
-</div>
-
-<script>
-showDefaultopenPopoversOnLoad();
-
-function runTest() {
-  document.body.offsetLeft; // Force layout
-
-  document.getElementById('popover1').setAttribute('anchor', 'anchor1');
-  document.getElementById('will-be-anchor2').setAttribute('id', 'anchor2');
-}
-window.addEventListener('load', runTest);
-</script>
-
-<style>
-  .ex {
-    margin: 25px;
-  }
-  .ex div {
-    width: 100px;
-    height: 100px;
-  }
-  .anchor {
-    background: orange;
-  }
-  [popover] {
-    inset: auto;
-    background: lime;
-    padding:0;
-    border:0;
-    left: anchor(right);
-    top: anchor(top);
-  }
-</style>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-display-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-display-ref.html
deleted file mode 100644
index 7b8410f6..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-display-ref.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<link rel=author href="mailto:masonf@chromium.org">
-
-<p>There should be a green box attached to the right side of each orange box.</p>
-<div id=proper_anchors class=wrapper>
-  <div><div class=anchor></div><div class=popover></div></div>
-  <div><div class=anchor></div><div class=popover></div></div>
-  <div><div class=anchor></div><div class=popover></div></div>
-  <div><div class=anchor></div><div class=popover></div></div>
-  <div><div class=anchor></div><div class=popover></div></div>
-  <div><div class=anchor></div><div class=popover></div></div>
-</div>
-
-<p>There should NOT be any red boxes next to the orange ones. (Red ones down below are ok.)</p>
-<div id=improper_anchors class=wrapper>
-  <div><div class=anchor></div><div class=popover></div></div>
-  <div><div class=anchor></div><div class=popover></div></div>
-</div>
-
-<style>
-  body { margin:0; padding:0; box-sizing: border-box; }
-  p {height: 25px;}
-  .wrapper {
-    display: flex;
-    flex-direction: row;
-    flex-wrap: wrap;
-  }
-  .wrapper>div {
-    position:relative;
-    width: 125px;
-    height: 75px;
-    font-size: 0;
-  }
-  .wrapper>div div {
-    display:inline-block;
-    width: 50px;
-    height: 50px;
-  }
-  .anchor {
-    background: orange;
-  }
-  #proper_anchors .popover {
-    background: lime;
-  }
-  #improper_anchors .popover {
-    background: red;
-    position:fixed;
-    left: 0;
-    top: 0;
-  }
-</style>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-display.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-display.tentative.html
deleted file mode 100644
index 1475c7de..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-display.tentative.html
+++ /dev/null
@@ -1,153 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<link rel=author href="mailto:masonf@chromium.org">
-<link rel=help href="https://open-ui.org/components/popover.research.explainer">
-<link rel=help href="https://html.spec.whatwg.org/multipage/popover.html">
-<link rel=match href="popover-anchor-display-ref.html">
-<link rel=stylesheet href="/fonts/ahem.css">
-<script src="resources/popover-utils.js"></script>
-
-<p>There should be a green box attached to the right side of each orange box.</p>
-
-<div id=proper_anchors class=wrapper>
-  <!-- Example using the `anchor` implicit reference element -->
-  <div>
-    <div class=anchor id=anchor1></div>
-    <div id=popover1 popover=manual anchor=anchor1></div>
-  </div>
-
-  <!-- Example with `anchor` attribute but not using it for anchor pos -->
-  <div>
-    <div id=anchor2 class=anchor></div>
-    <div id=popover2 popover=manual anchor></div>
-  </div>
-
-  <!-- Example using `anchor-name` plus inset, and no `anchor` attribute -->
-  <div>
-    <div id=anchor3 class=anchor></div>
-    <div id=popover3 popover=manual></div>
-  </div>
-
-  <!-- Example using implicit anchor reference and inline anchor element -->
-  <div>
-    <span id=anchor4>X</span>
-    <div id=popover4 popover=manual anchor=anchor4></div>
-  </div>
-
-  <!-- Example using a default anchor which is not the implicit anchor -->
-  <div>
-    <div class=anchor id=anchor5></div>
-    <!-- Note `anchor=anchor1` here, not anchor5 -->
-    <div id=popover5 popover=manual anchor=anchor1></div>
-  </div>
-
-  <!-- Example using implicit anchor reference and position-anchor:auto -->
-  <div>
-    <div class=anchor id=anchor6></div>
-    <div id=popover6 popover=manual anchor=anchor6></div>
-  </div>
-</div>
-
-<p>There should NOT be any red boxes next to the orange ones. (Red ones down below are ok.)</p>
-
-<div id=improper_anchors class=wrapper>
-  <!-- Example using implicit anchor reference and anchor(auto foo)-->
-  <div>
-    <div class=anchor id=anchor7></div>
-    <div id=popover7 popover=manual anchor=anchor7></div>
-  </div>
-
-  <!-- Example using invalid anchor name -->
-  <div>
-    <div class=anchor id=anchor8></div>
-    <div id=popover8 popover=manual anchor=anchor8></div>
-  </div>
-</div>
-
-<script>
-  Array.from(document.querySelectorAll('[popover=manual]')).forEach(p => p.showPopover());
-</script>
-
-<style>
-  body { margin:0; padding:0; box-sizing: border-box; }
-  p {height: 25px;}
-  .wrapper {
-    display: flex;
-    flex-direction: row;
-    flex-wrap: wrap;
-  }
-  .wrapper>div {
-    position:relative;
-    width: 125px;
-    height: 75px;
-  }
-  .wrapper>div div {
-    width: 50px;
-    height: 50px;
-  }
-  .anchor {
-    background: orange;
-  }
-  [popover] {
-    inset: auto;
-    padding:0;
-    border:0;
-  }
-  #proper_anchors [popover] {
-    background: lime;
-  }
-  #improper_anchors [popover] {
-    background: red;
-  }
-  #popover1 {
-    left: anchor(right);
-    top: anchor(top);
-  }
-  #anchor2 {
-    anchor-name: --anchor2;
-  }
-  #popover2 {
-    left: anchor(--anchor2 right);
-    top: anchor(--anchor2 top);
-  }
-  #anchor3 {
-    anchor-name: --anchor3;
-  }
-  #popover3 {
-    inset:auto;
-    left: anchor(--anchor3 right);
-    top: anchor(--anchor3 top);
-  }
-  #anchor4 {
-    font-family: Ahem;
-    font-size: 50px;
-    color: orange;
-  }
-  #popover4 {
-    left: anchor(right);
-    top: anchor(top);
-  }
-  #anchor5 {
-    anchor-name: --anchor5;
-  }
-  #popover5 {
-    position-anchor: --anchor5;
-    left: anchor(right); /* shouldn't use the implicit anchor */
-    top: anchor(top);
-  }
-  #popover6 {
-    position-anchor: auto;
-    left: anchor(right);
-    top: anchor(top);
-  }
-  #popover7 {
-    left: anchor(auto right);
-    top: anchor(auto top);
-  }
-  #popover8 {
-    /* The `implicit` keyword was renamed to `auto`, and anyway should not
-    work in this context. */
-    left: anchor(implicit right);
-    top: anchor(implicit top);
-  }
-</style>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-idl-property.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-idl-property.tentative.html
deleted file mode 100644
index 1e255339..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-idl-property.tentative.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<link rel="author" href="mailto:masonf@chromium.org">
-<link rel=help href="https://open-ui.org/components/popover.research.explainer">
-<link rel=help href="https://html.spec.whatwg.org/multipage/popover.html">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<div>
-  <button id=b1>This is an anchor button</button>
-  <div popover id=p1 anchor=b1>This is a popover</div>
-  <button id=b2 popovertarget=p1>This button invokes the popover but isn't an anchor</button>
-</div>
-
-<script>
-  test(function() {
-    assert_equals(p1.anchorElement,b1);
-  }, "popover anchorElement IDL property returns the anchor element");
-
-  test(function() {
-    assert_equals(p1.anchorElement,b1);
-    p1.anchorElement = b2;
-    assert_equals(p1.anchorElement,b2);
-    assert_equals(p1.getAttribute('anchor'),'','Idref is empty after setting element');
-    p1.anchorElement = b1; // Reset
-  }, "popover anchorElement is settable");
-</script>
-
-<div>
-  <button id=b3>button</button>
-  <div id=p2>Anchored div</div>
-</div>
-<style>
-  * {margin:0;padding:0;}
-  #b3 {width: 200px;}
-  #p2 {
-    position: absolute;
-    left: anchor(right);
-  }
-</style>
-
-<script>
-  test(function() {
-    assert_equals(p2.anchorElement,null);
-    const button = document.getElementById('b3');
-    assert_true(!!button);
-    p2.anchorElement = button;
-    assert_equals(p2.getAttribute('anchor'),'','Idref should be empty after setting element');
-    assert_equals(p2.anchorElement,button,'Element reference should be button');
-    assert_equals(p2.offsetLeft, 200, 'The anchor relationship should be functional');
-  }, "anchorElement affects anchor positioning");
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-inset-rule-display-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-inset-rule-display-ref.html
deleted file mode 100644
index 1cd13d0..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-inset-rule-display-ref.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<link rel="stylesheet" href="resources/popover-styles.css">
-
-<div class="fake-popover" anchor></div>
-
-<style>
-  .fake-popover {
-    background: green;
-    width: 100px;
-    height: 100px;
-  }
-  body { margin: 0; }
-</style>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-inset-rule-display.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-inset-rule-display.tentative.html
deleted file mode 100644
index 72395cc71..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-inset-rule-display.tentative.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<link rel=author href="mailto:masonf@chromium.org">
-<link rel=help href="https://html.spec.whatwg.org/multipage/popover.html">
-<link rel=match href="popover-anchor-inset-rule-display-ref.html">
-
-<div popover=manual anchor></div>
-
-<style>
-  [popover][anchor] {
-    background: green;
-    width: 100px;
-    height: 100px;
-  }
-  body { margin: 0; }
-</style>
-
-<script>
-  document.querySelector('[popover]').showPopover();
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-multicol-display.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-multicol-display.html
similarity index 88%
rename from third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-multicol-display.tentative.html
rename to third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-multicol-display.html
index f8db954..2387950 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-multicol-display.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-multicol-display.html
@@ -25,6 +25,7 @@
   width: 10px;
   height: 30px;
   background: orange;
+  anchor-name: --anchor1;
 }
 .target {
   /*
@@ -39,6 +40,7 @@
   width: anchor-size(width);
   height: anchor-size(height);
   background: lime;
+  position-anchor: --anchor1;
 }
 </style>
 <body onload="checkLayout('.target')">
@@ -52,9 +54,9 @@
           <div class="spacer" style="height: 10px"></div>
           <div id="anchor1"></div>
         </div>
-        <div class="target" popover anchor="anchor1" data-expected-height=30></div>
+        <div class="target" popover data-expected-height=30></div>
       </div>
-      <div class="target" popover anchor="anchor1" data-expected-height=50></div>
+      <div class="target" popover data-expected-height=50></div>
     </div>
   </div>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-scroll-display-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-scroll-display-ref.html
deleted file mode 100644
index 926a171..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-scroll-display-ref.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-
-<div class=spacer style="height: 200px"></div>
-
-<p>There should be a green box attached to the right side of each orange box.</p>
-<div class=ex id=ex1><div class=anchor></div><div class=popover></div></div>
-<div class=ex id=ex2><div class=anchor></div><div class=popover></div></div>
-
-<div class=spacer style="height: 200vh"></div>
-
-<style>
-  .ex {
-    margin: 25px;
-    font-size: 0;
-  }
-  .ex div {
-    display:inline-block;
-    width: 100px;
-    height: 100px;
-  }
-  .anchor {
-    background: orange;
-  }
-  .popover {
-    background: lime;
-  }
-</style>
-
-<script>
-document.documentElement.scrollTop = 100;
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-scroll-display.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-scroll-display.tentative.html
deleted file mode 100644
index a301032a..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-anchor-scroll-display.tentative.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-<meta charset="utf-8">
-<link rel=author href="mailto:xiaochengh@chromium.org">
-<link rel=help href="https://open-ui.org/components/popover.research.explainer">
-<link rel=help href="https://html.spec.whatwg.org/multipage/popover.html">
-<link rel=match href="popover-anchor-scroll-display-ref.html">
-
-<div class=spacer style="height: 200px"></div>
-
-<p>There should be a green box attached to the right side of each orange box.</p>
-
-<!-- Example using the `anchor` implicit reference element -->
-<div class=ex>
-  <div class=anchor id=anchor1></div>
-  <div id=popover1 popover=manual anchor=anchor1></div>
-</div>
-
-<!-- Example using a default anchor that is not the implicit anchor -->
-<div class=ex>
-  <div class=anchor id=anchor2></div>
-  <div id=popover2 popover=manual anchor=fake-anchor></div>
-</div>
-
-<!-- A position:fixed fake anchor. Any popover anchored to it won't move when
-     the document is scrolled. -->
-<div id=fake-anchor></div>
-
-<div class=spacer style="height: 200vh"></div>
-
-<style>
-  .ex {
-    margin: 25px;
-  }
-  .ex div {
-    width: 100px;
-    height: 100px;
-  }
-  .anchor {
-    background: orange;
-  }
-  [popover] {
-    inset: auto;
-    background: lime;
-    padding:0;
-    border:0;
-  }
-  #popover1 {
-    left: anchor(right);
-    top: anchor(top);
-  }
-  #fake-anchor {
-    position: fixed;
-    anchor-name: --fake-anchor;
-  }
-  #anchor2 {
-    anchor-name: --anchor2;
-  }
-  #popover2 {
-    position-anchor: --anchor2;
-    left: anchor(right);
-    top: anchor(top);
-  }
-</style>
-
-<script>
-function raf() {
-  return new Promise(resolve => requestAnimationFrame(resolve));
-}
-
-async function runTest() {
-  document.querySelectorAll('[popover]').forEach(
-      popover => popover.showPopover());
-
-  // Render a frame at the intial scroll position.
-  await raf();
-  await raf();
-
-  document.documentElement.scrollTop = 100;
-  document.documentElement.classList.remove('reftest-wait');
-
-  // The popover should still be attached to the anchor.
-}
-runTest();
-</script>
-
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-with-anchor.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-with-anchor.tentative.html
deleted file mode 100644
index c4e545c..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-with-anchor.tentative.html
+++ /dev/null
@@ -1,90 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8" />
-<title>Popover light dismiss with anchor behavior</title>
-<meta name="timeout" content="long">
-<link rel="author" href="mailto:masonf@chromium.org">
-<link rel=help href="https://open-ui.org/components/popover.research.explainer">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/testdriver.js"></script>
-<script src="/resources/testdriver-actions.js"></script>
-<script src="/resources/testdriver-vendor.js"></script>
-<script src="resources/popover-utils.js"></script>
-
-<button id=p1anchor  tabindex="0">Popover1 anchor (no action)</button>
-<div popover id=p1 anchor=p1anchor>
-  <span id=inside1>Inside popover 1</span>
-  <button id=b2 popovertarget='p2' popovertargetaction=show>Popover 2</button>
-</div>
-<div popover id=p2 anchor=b2>
-  <span id=inside2>Inside popover 2</span>
-</div>
-<style>
-  #p1 {top: 50px;}
-  #p2 {top: 120px;}
-  [popover] {bottom:auto;}
-  [popover]::backdrop {
-    /* This should *not* affect anything: */
-    pointer-events: auto;
-  }
-</style>
-<script>
-  const popover1 = document.querySelector('#p1');
-  const popover1anchor = document.querySelector('#p1anchor');
-  const popover2 = document.querySelector('#p2');
-  const inside1 = document.querySelector('#inside1');
-  const inside2 = document.querySelector('#inside2');
-
-  let popover1HideCount = 0;
-  popover1.addEventListener('beforetoggle',(e) => {
-    if (e.newState !== "closed")
-      return;
-    ++popover1HideCount;
-    e.preventDefault(); // 'beforetoggle' should not be cancellable.
-  });
-  let popover2HideCount = 0;
-  popover2.addEventListener('beforetoggle',(e) => {
-    if (e.newState !== "closed")
-      return;
-    ++popover2HideCount;
-    e.preventDefault(); // 'beforetoggle' should not be cancellable.
-  });
-
-  promise_test(async () => {
-    popover1.showPopover();
-    popover2.showPopover();
-    await waitForRender();
-    p1HideCount = popover1HideCount;
-    let p2HideCount = popover2HideCount;
-    await clickOn(inside2);
-    assert_true(popover1.matches(':popover-open'),'popover1 should be open');
-    assert_true(popover2.matches(':popover-open'),'popover2 should be open');
-    assert_equals(popover1HideCount,p1HideCount,'popover1');
-    assert_equals(popover2HideCount,p2HideCount,'popover2');
-    popover1.hidePopover();
-    assert_false(popover1.matches(':popover-open'));
-    assert_false(popover2.matches(':popover-open'));
-  },'Clicking inside a child popover shouldn\'t close either popover');
-
-  promise_test(async () => {
-    popover1.showPopover();
-    popover2.showPopover();
-    await waitForRender();
-    p1HideCount = popover1HideCount;
-    p2HideCount = popover2HideCount;
-    await clickOn(inside1);
-    assert_true(popover1.matches(':popover-open'));
-    assert_equals(popover1HideCount,p1HideCount);
-    assert_false(popover2.matches(':popover-open'));
-    assert_equals(popover2HideCount,p2HideCount+1);
-    popover1.hidePopover();
-  },'Clicking inside a parent popover should close child popover');
-
-  promise_test(async () => {
-    popover1.showPopover();
-    assert_true(popover1.matches(':popover-open'));
-    await waitForRender();
-    await clickOn(popover1anchor);
-    assert_false(popover1.matches(':popover-open'),'popover1 should close');
-  },'Clicking on anchor element (that isn\'t an invoking element) shouldn\'t prevent its popover from being closed');
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-shadow-dom-anchor.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-shadow-dom-anchor.tentative.html
deleted file mode 100644
index 7c87d2d..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-shadow-dom-anchor.tentative.html
+++ /dev/null
@@ -1,99 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<link rel="author" href="mailto:masonf@chromium.org">
-<link rel=help href="https://open-ui.org/components/popover.research.explainer">
-<link rel=help href="https://html.spec.whatwg.org/multipage/popover.html">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/popover-utils.js"></script>
-
-<!-- Once anchor positioning lands in the spec, the tests in this file can
-     be re-inserted into popover-shadow-dom.html. -->
-
-<script>
-  function findPopovers(root) {
-    let popovers = [];
-    if (!root)
-      return popovers;
-    if (root instanceof Element && root.matches('[popover]'))
-      popovers.push(root);
-    popovers.push(...findPopovers(root.shadowRoot));
-    root.childNodes.forEach(child => {
-      popovers.push(...findPopovers(child));
-    })
-    return popovers;
-  }
-  function getPopoverReferences(testId) {
-    const testRoot = document.querySelector(`#${testId}`);
-    assert_true(!!testRoot);
-    return findPopovers(testRoot);
-  }
-</script>
-
-<div id=test1>
-  <button id=t2b1>Test 1 Popover 1</button>
-  <div popover anchor=t2b1 style="top: 200px;">
-    <p>Popover 1</p>
-    <button id=t2b2>Test 1 Popover 2</button>
-  </div>
-  <my-element>
-    <template shadowrootmode=open>
-      <div popover anchor=t2b2 style="top: 400px;">
-        <p>Hiding this popover will hide *all* open popovers,</p>
-        <p>because t2b2 doesn't exist in this context.</p>
-      </div>
-    </template>
-  </my-element>
-</div>
-
-<script>
-  test(function() {
-    const [popover1,popover2] = getPopoverReferences('test1');
-    popover1.showPopover();
-    assert_true(popover1.matches(':popover-open'));
-    assert_true(isElementVisible(popover1));
-    popover2.showPopover();
-    assert_false(popover1.matches(':popover-open'), 'popover1 open'); // P1 was closed by P2
-    assert_false(isElementVisible(popover1), 'popover1 visible');
-    assert_true(popover2.matches(':popover-open'), 'popover2 open'); // P2 is open
-    assert_true(isElementVisible(popover2), 'popover2 visible');
-    popover2.hidePopover(); // Cleanup
-  }, "anchor references do not cross shadow boundaries");
-</script>
-
-
-<div id=test2>
-  <my-element>
-    <template shadowrootmode=open>
-      <button id=t3b1>Test 2 Popover 1</button>
-      <div popover anchor=t3b1>
-        <p>This popover will stay open when popover2 shows.</p>
-        <slot></slot>
-      </div>
-    </template>
-    <button id=t3b2>Test 2 Popover 2</button>
-  </my-element>
-  <div popover anchor=t3b2>Popover 2</div>
-</div>
-
-<script>
-  promise_test(async function() {
-    const [popover1,popover2] = getPopoverReferences('test2');
-    popover1.showPopover();
-    assert_true(popover1.matches(':popover-open'));
-    assert_true(isElementVisible(popover1));
-    // Showing popover2 should not close popover1, since it is a flat
-    // tree ancestor of popover2's anchor button.
-    popover2.showPopover();
-    assert_true(popover2.matches(':popover-open'));
-    assert_true(isElementVisible(popover2));
-    assert_true(popover1.matches(':popover-open'));
-    assert_true(isElementVisible(popover1));
-    popover1.hidePopover();
-    await waitForRender();
-    assert_false(popover1.matches(':popover-open'));
-    assert_false(isElementVisible(popover1));
-    assert_false(popover2.matches(':popover-open'));
-    assert_false(isElementVisible(popover2));
-  }, "anchor references use the flat tree not the DOM tree");
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-stacking-anchor-attribute.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-stacking-anchor-attribute.tentative.html
deleted file mode 100644
index 6895b86..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-stacking-anchor-attribute.tentative.html
+++ /dev/null
@@ -1,104 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<link rel="author" href="mailto:masonf@chromium.org">
-<link rel=help href="https://www.w3.org/TR/css-anchor-position-1/#implicit">
-<link rel=help href="https://html.spec.whatwg.org/multipage/popover.html">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<!-- Once this test is made non-tentative, it can be folded back into popover-stacking.html -->
-
-<div class="example">
-  <p>anchor attribute relationship</p>
-  <div id=anchor1 popover class=ancestor><p>Ancestor popover</p></div>
-  <div anchor=anchor1 popover class=child><p>Child popover</p></div>
-</div>
-
-<div class="example">
-  <p>indirect anchor attribute relationship</p>
-  <div popover class=ancestor>
-    <p>Ancestor popover</p>
-    <div>
-      <div>
-        <span id=anchor2>Anchor</span>
-      </div>
-    </div>
-  </div>
-  <div anchor=anchor2 popover class=child><p>Child popover</p></div>
-</div>
-
-<!-- Other examples -->
-
-<div popover id=p1 anchor=b1><p>This is popover #1</p>
-  <button id=b2 onclick='p2.showPopover()'>Popover 2</button>
-  <button id=b4 onclick='p4.showPopover()'>Popover 4</button>
-</div>
-<div popover id=p2 anchor=b2><p>This is popover #2</p>
-  <button id=b3 onclick='p3.showPopover()'>Popover 3</button>
-</div>
-<div popover id=p3 anchor=b3><p>This is popover #3</p></div>
-<div popover id=p4 anchor=b4><p>This is popover #4</p></div>
-<button id=b1 onclick='p1.showPopover()'>Popover 1</button>
-
-<dialog id=d1>This is a dialog<button onclick='this.parentElement.close()'>Close</button></dialog>
-<button id=b5 onclick='d1.showPopover()'>Dialog</button>
-
-<script>
-  // Test basic ancestor relationships
-  for(let example of document.querySelectorAll('.example')) {
-    const descr = example.querySelector('p').textContent;
-    const ancestor = example.querySelector('[popover].ancestor');
-    const child = example.querySelector('[popover].child');
-    const clickToActivate = example.querySelector('.clickme');
-    test(function() {
-      assert_true(!!descr && !!ancestor && !!child);
-      assert_false(ancestor.matches(':popover-open'));
-      assert_false(child.matches(':popover-open'));
-      ancestor.showPopover();
-      if (clickToActivate)
-        clickToActivate.click();
-      else
-        child.showPopover();
-      assert_true(child.matches(':popover-open'));
-      assert_true(ancestor.matches(':popover-open'));
-      ancestor.hidePopover();
-      assert_false(ancestor.matches(':popover-open'));
-      assert_false(child.matches(':popover-open'));
-    },descr);
-  }
-
-  const popovers = [p1, p2, p3, p4];
-
-  function assertState(...states) {
-    assert_equals(popovers.length,states.length);
-    for(let i=0;i<popovers.length;++i) {
-      assert_equals(popovers[i].matches(':popover-open'),states[i],`Popover #${i+1} incorrect state`);
-    }
-  }
-  test(function() {
-    assertState(false,false,false,false);
-    p1.showPopover();
-    assertState(true,false,false,false);
-    p2.showPopover();
-    assertState(true,true,false,false);
-    p3.showPopover();
-    assertState(true,true,true,false);
-    // P4 is a sibling of P2, so showing it should
-    // close P2 and P3.
-    p4.showPopover();
-    assertState(true,false,false,true);
-    // P2 should close P4 now.
-    p2.showPopover();
-    assertState(true,true,false,false);
-    // Hiding P1 should hide all.
-    p1.hidePopover();
-    assertState(false,false,false,false);
-  }, "more complex nesting, all using anchor ancestry")
-</script>
-
-<style>
-  #p1 { top:350px; }
-  #p2 { top:350px; left:200px; }
-  #p3 { top:500px; }
-  #p4 { top:500px;left:200px; }
-</style>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-types-with-hints-and-anchor.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-types-with-hints-and-anchor.tentative.html
deleted file mode 100644
index 9f2ae8b..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-types-with-hints-and-anchor.tentative.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<link rel="author" href="mailto:masonf@chromium.org">
-<link rel=help href="https://open-ui.org/components/popover.research.explainer">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<script>
-  function getPopovers() {
-    return Array.from(document.currentScript.parentElement.querySelectorAll('[popover]'));
-  }
-  function assertState(expectedState,description) {
-    description = description || 'Error';
-    const popovers = getPopovers();
-    const n = popovers.length;
-    assert_equals(expectedState.length,n,'Invalid expected state length');
-    for(let i=0;i<n;++i) {
-      const html = '<' + popovers[i].outerHTML.split('<')[1] + '</div>';
-      assert_equals(popovers[i].matches(':popover-open'),expectedState[i],`${description}, index ${i} (${html})`);
-    }
-  }
-</script>
-
-<div>
-  <div popover>popover 1
-    <div popover>popover 2
-      <p id=anchorid>Anchor</p>
-      <div popover>popover 3</div>
-    </div>
-  </div>
-  <div popover=hint anchor=anchorid>Hint anchored to popover</div>
-  <script>
-  {
-    const popover1 = getPopovers()[0];
-    const popover2 = getPopovers()[1];
-    const popover3 = getPopovers()[2];
-    const hint = getPopovers()[3];
-    test(() => {
-      assertState([false,false,false,false]);
-      popover1.showPopover();
-      popover2.showPopover();
-      popover3.showPopover();
-      assertState([true,true,true,false]);
-      hint.showPopover(); // Because hint is nested in popover2, popover3 should be hidden
-      assertState([true,true,false,true]);
-      popover1.hidePopover(); // Should close the hint, which is anchored to popover2
-      assertState([false,false,false,false]);
-    },'hint is not closed by pre-existing auto');
-  }
-  </script>
-</div>
-
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-top-layer-nesting.js b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-top-layer-nesting.js
index affb08c..e6dcd300 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-top-layer-nesting.js
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-top-layer-nesting.js
@@ -21,8 +21,7 @@
   t.add_cleanup(() => element.remove());
   return {element,show,showing};
 }
-function runTopLayerTests(testCases, testAnchorAttribute) {
-  testAnchorAttribute = testAnchorAttribute || false;
+function runTopLayerTests(testCases) {
   testCases.forEach(test => {
     const description = test.firstChild.data.trim();
     assert_equals(test.querySelectorAll('.target').length,1,'There should be exactly one target');
@@ -85,24 +84,6 @@
           }
         }
       },`${description} with ${topLayerType}, top layer element *is* a popover`);
-
-      if (testAnchorAttribute) {
-        promise_test(async t => {
-          const {element,show,showing} = createTopLayerElement(t,topLayerType);
-          element.anchorElement = target;
-          document.body.appendChild(element);
-
-          // Show the popovers.
-          t.add_cleanup(() => popovers.forEach(popover => popover.hidePopover()));
-          popovers.forEach(popover => popover.showPopover());
-          popovers.forEach(popover => assert_true(popover.matches(':popover-open'),'All popovers should be open'));
-
-          // Activate the top layer element.
-          await show(popovers[popovers.length-1]);
-          assert_true(showing());
-          popovers.forEach(popover => assert_equals(popover.matches(':popover-open'),popover.dataset.stayOpen==='true','Incorrect behavior'));
-        },`${description} with ${topLayerType}, anchor attribute`);
-      }
     });
   });
 }
diff --git a/third_party/blink/web_tests/external/wpt/sanitizer-api/sethtml-with-trustedtypes-createParserOptions.tentative.html b/third_party/blink/web_tests/external/wpt/sanitizer-api/sethtml-with-trustedtypes-createParserOptions.tentative.html
new file mode 100644
index 0000000..0feacc5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/sanitizer-api/sethtml-with-trustedtypes-createParserOptions.tentative.html
@@ -0,0 +1,68 @@
+<!doctype html>
+<html>
+  <head>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/trusted-types/support/helper.sub.js"></script>
+
+    <meta
+      http-equiv="Content-Security-Policy"
+      content="require-trusted-types-for 'script';"
+    />
+  </head>
+  <body>
+    <div id="container"></div>
+    <script>
+      const container = document.querySelector("#container");
+      // We have to replace this global because we are overriding the default policy from within the test.
+      let createParserOptions = (options) => options;
+      let createHTML = (html) => html;
+      const cleanupPolicy = trustedTypes.createPolicy("cleanup", {
+        createHTML: (_) => "",
+      });
+
+      trustedTypes.createPolicy("default", {
+        createHTML: (html) => createHTML(html),
+        createParserOptions: (options) => ({
+          sanitizer: { removeElements: ["div"] },
+        }),
+      });
+
+      const passthrough = trustedTypes.createPolicy("passthrough", {
+        createHTML: (html) => createHTML(html),
+        createParserOptions: (options) => options,
+      });
+
+      function cleanup() {}
+
+      function createTarget(target_type, t) {
+        t.add_cleanup(() => {
+          createParserOptions = (options) => options;
+          createHTML = (html) => html;
+        });
+
+        const target = document.createElement("div");
+        switch (target_type) {
+          case "Element":
+            return target;
+          case "ShadowRoot":
+            return target.attachShadow({ mode: "open" });
+        }
+      }
+
+      for (const target of ["ShadowRoot", "Element"]) {
+        test((t) => {
+          const node = createTarget(target, t);
+          node.setHTMLUnsafe(
+            "<div id='allowed'><span id=forbidden></span></div>",
+            passthrough.createParserOptions({
+              sanitizer: { removeElements: ["span"] },
+            }),
+          );
+          assert_equals(node.querySelector("#forbidden"), null);
+          assert_not_equals(node.querySelector("#allowed"), null);
+        }, `${target}.setHTMLUnsafe: passing a TrustedParserOptions overrides default policy`);
+      }
+    </script>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/sanitizer-api/sethtml-with-trustedtypes-immutable.tentative.html b/third_party/blink/web_tests/external/wpt/sanitizer-api/sethtml-with-trustedtypes-immutable.tentative.html
new file mode 100644
index 0000000..5e8484e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/sanitizer-api/sethtml-with-trustedtypes-immutable.tentative.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+  <head>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/trusted-types/support/helper.sub.js"></script>
+
+    <meta
+      http-equiv="Content-Security-Policy"
+      content="require-trusted-types-for 'script';"
+    />
+  </head>
+  <body>
+    <div id="container"></div>
+    <script>
+      const container = document.querySelector("#container");
+      // We have to replace this global because we are overriding the default policy from within the test.
+      trustedTypes.createPolicy("default", {
+        createHTML: (html) => html,
+        createParserOptions: (options) => {
+          options.modified = true;
+          if (options.sanitizer instanceof Sanitizer) {
+            options.sanitizer.removeElement("span");
+            options.sanitizer.allowAttribute("id");
+          } else if (
+            options.sanitizer &&
+            typeof options.sanitizer === "object"
+          ) {
+            options.sanitizer.removeElements = ["span"];
+          }
+          return options;
+        },
+      });
+
+      for (const method of ["setHTML", "setHTMLUnsafe"]) {
+        test((t) => {
+          let d = document.createElement("div");
+          document.querySelector("#container").appendChild(d);
+          t.add_cleanup(() => d.remove());
+          const options = { sanitizer: {}, modified: false };
+          d[method](
+            "<div id='allowed'><span id=forbidden></span></div>",
+            options,
+          );
+          assert_false(
+            options.modified,
+            "trusted types policy should not modify given options",
+          );
+          assert_false(
+            "removeElements" in options.sanitizer,
+            "trusted types policy should not modify sanitizer",
+          );
+          assert_equals(d.querySelector("#forbidden"), null);
+          assert_not_equals(d.querySelector("#allowed"), null);
+        }, `${method}: createParserOptions doesn't mutate original object`);
+
+        test((t) => {
+          let d = document.createElement("div");
+          document.querySelector("#container").appendChild(d);
+          t.add_cleanup(() => d.remove());
+          const options = { sanitizer: new Sanitizer() };
+          d[method](
+            "<div id=allowed><span id=forbidden></span></div>",
+            options,
+          );
+          assert_false(
+            "removeElements" in options.sanitizer.get(),
+            "trusted types policy should not modify sanitizer",
+          );
+          assert_equals(d.querySelector("#forbidden"), null);
+          assert_not_equals(d.querySelector("#allowed"), null);
+        }, `${method}: createParserOptions doesn't mutate sanitizer object`);
+      }
+    </script>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/sanitizer-api/sethtml-with-trustedtypes.tentative.html b/third_party/blink/web_tests/external/wpt/sanitizer-api/sethtml-with-trustedtypes.tentative.html
new file mode 100644
index 0000000..d156b26
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/sanitizer-api/sethtml-with-trustedtypes.tentative.html
@@ -0,0 +1,250 @@
+<!doctype html>
+<html>
+  <head>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/trusted-types/support/helper.sub.js"></script>
+
+    <meta
+      http-equiv="Content-Security-Policy"
+      content="require-trusted-types-for 'script';"
+    />
+  </head>
+  <body>
+    <div id="container"></div>
+    <script>
+      const container = document.querySelector("#container");
+      // We have to replace this global because we are overriding the default policy from within the test.
+      let createParserOptions = (options) => options;
+      let createHTML = (html) => html;
+      const cleanupPolicy = trustedTypes.createPolicy("cleanup", {
+        createHTML: (_) => "",
+      });
+
+      trustedTypes.createPolicy("default", {
+        createHTML: (html) => createHTML(html),
+        createParserOptions: (options) => createParserOptions(options),
+      });
+
+      function cleanup() {}
+
+      function createTarget(target_type, t) {
+        t.add_cleanup(() => {
+          createParserOptions = (options) => options;
+          createHTML = (html) => html;
+        });
+
+        const target = document.createElement("div");
+        container.append(target);
+        t.add_cleanup(() => target.remove());
+        switch (target_type) {
+          case "Element":
+            return target;
+          case "ShadowRoot":
+            return target.attachShadow({ mode: "open" });
+        }
+      }
+
+      /**
+       *
+       * @param {Element|ShadowRoot} node
+       * @param {string} method
+       * @param {string} html
+       */
+      function run_method(node, method, html) {
+        switch (method) {
+          case "innerHTML":
+            node[method] = html;
+            break;
+          case "outerHTML": {
+            const inner = document.createElement("div");
+            node.replaceChildren(inner);
+            inner[method] = html;
+            break;
+          }
+          case "afterbegin":
+          case "beforeend": {
+            node.insertAdjacentHTML(method, html);
+            break;
+          }
+          case "beforebegin":
+          case "afterend": {
+            const inner = document.createElement("div");
+            node.replaceChildren(inner);
+            inner.insertAdjacentHTML(method, html);
+            break;
+          }
+          case "createContextualFragment":
+            const range = document.createRange();
+            range.setStart(node, 0);
+            range.setEnd(node, 0);
+            range.insertNode(range.createContextualFragment(html));
+            break;
+          default:
+            node[method](html);
+        }
+      }
+
+      for (const target of ["ShadowRoot", "Element"]) {
+        for (const method of [
+          "setHTML",
+          "setHTMLUnsafe",
+          "innerHTML",
+          "outerHTML",
+          "createContextualFragment",
+          "afterbegin",
+          "beforeend",
+          "beforebegin",
+          "afterend",
+        ]) {
+          if (
+            target === "ShadowRoot" &&
+            (method === "outerHTML" ||
+              method === "afterbegin" ||
+              method === "beforeend" ||
+              method === "createContextualFragment")
+          ) {
+            continue;
+          }
+          test((t) => {
+            const node = createTarget(target, t);
+            createParserOptions = (options) => ({
+              ...options,
+              sanitizer: { removeElements: ["span"] },
+            });
+            run_method(
+              node,
+              method,
+              "<div id='allowed'><span id=forbidden></span></div>",
+            );
+            assert_equals(node.querySelector("#forbidden"), null);
+            assert_not_equals(node.querySelector("#allowed"), null);
+          }, `${target}.${method}: createParserOptions can inject a sanitizer config`);
+
+          test((t) => {
+            t.add_cleanup(cleanup);
+            const node = createTarget(target, t);
+            createParserOptions = (options) => ({
+              ...options,
+              sanitizer: new Sanitizer({ removeElements: ["span"] }),
+            });
+            run_method(
+              node,
+              method,
+              "<div id=allowed><span id=forbidden></span></div>",
+            );
+            assert_equals(node.querySelector("#forbidden"), null);
+            assert_not_equals(node.querySelector("#allowed"), null);
+          }, `${target}.${method}: createParserOptions can inject a sanitizer`);
+
+          test((t) => {
+            const node = createTarget(target, t);
+            createParserOptions = (options) => ({
+              sanitizer: { removeElements: ["span"] },
+            });
+            run_method(
+              node,
+              method,
+              "<div id=allowed><span id=forbidden></span></div>",
+              {
+                sanitizer: { removeElements: ["div"] },
+              },
+            );
+            assert_equals(node.querySelector("#forbidden"), null);
+            assert_not_equals(node.querySelector("#allowed"), null);
+          }, `${target}.${method}: createParserOptions can override a sanitizer config`);
+
+          test((t) => {
+            const node = createTarget(target, t);
+            createParserOptions = (options) => ({});
+            run_method(node, method, "<div id=allowed></div>", {
+              sanitizer: { removeElements: ["div"] },
+            });
+            assert_equals(node.querySelector("#forbidden"), null);
+            assert_not_equals(node.querySelector("#allowed"), null);
+          }, `${target}.${method}: createParserOptions can remove a sanitizer`);
+
+          for (const value of [null, undefined, 0, 123, "foo"]) {
+            test((t) => {
+              const node = createTarget(target, t);
+              createParserOptions = (options) => value;
+              assert_throws_js(TypeError, () => {
+                run_method(
+                  node,
+                  method,
+                  "<div id='allowed'><span id=forbidden></span></div>",
+                );
+              });
+              assert_equals(node.querySelector("#forbidden"), null);
+              assert_equals(node.textContent, "");
+            }, `${target}.${method}: createParserOptions returning ${JSON.stringify(value)} fails`);
+          }
+        }
+
+        test((t) => {
+          const node = createTarget(target, t);
+          window.did_run = false;
+          t.add_cleanup(() => {
+            window.did_run = false;
+          });
+          createParserOptions = (options) => ({
+            runScripts: false,
+          });
+          node.setHTMLUnsafe(
+            "<div id=allowed><script>window.did_run = true;<" +
+              "/script></div>",
+          );
+          assert_false(window.did_run);
+          assert_not_equals(node.querySelector("#allowed"), null);
+        }, `${target}: createParserOptions can override runScripts`);
+
+        test((t) => {
+          const node = createTarget(target, t);
+          window.did_run = false;
+          t.add_cleanup(() => {
+            window.did_run = false;
+          });
+          createParserOptions = (options) => ({
+            runScripts: true,
+          });
+          (node.setHTMLUnsafe(
+            "<div id=allowed><script>window.did_run = true;<" +
+              "/script></div>",
+          ),
+            { runScripts: false });
+          assert_false(window.did_run);
+          assert_not_equals(node.querySelector("#allowed"), null);
+        }, `${target}: createParserOptions cannot change runScripts from false to true`);
+
+        test((t) => {
+          const node = createTarget(target, t);
+          createParserOptions = (options) => ({
+            ...options,
+            sanitizer: new Sanitizer({ removeElements: ["span"] }),
+          });
+          createHTML = (html) =>
+            html.replaceAll("cat", "<span id=forbidden2></span><p>dog</p>");
+          node.setHTMLUnsafe(
+            "<div id=allowed><span id=forbidden></span><div>cat</div></div>",
+          );
+          assert_equals(node.querySelector("#forbidden"), null);
+          assert_equals(node.querySelector("#forbidden2"), null);
+          assert_equals(node.textContent, "dog", node.innerHTML);
+          assert_not_equals(node.querySelector("#allowed"), null);
+        }, `${target}.setHTMLUnsafe: createParserOptions works after createHTML`);
+
+        test((t) => {
+          const node = createTarget(target, t);
+          window.did_run = false;
+          t.add_cleanup(() => {
+            window.did_run = false;
+          });
+          createParserOptions = (options) => ({ allowElements: ["script"] });
+          node.setHTML("<script id=forbidden><" + "/script>");
+          assert_false(window.did_run);
+          assert_equals(node.querySelector("#forbidden"), null);
+        }, `${target}: createParserOptions cannot add unsafe elements to safe HTML setting`);
+      }
+    </script>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/reference-target/tentative/anchor.html b/third_party/blink/web_tests/external/wpt/shadow-dom/reference-target/tentative/anchor.html
deleted file mode 100644
index dae4f08..0000000
--- a/third_party/blink/web_tests/external/wpt/shadow-dom/reference-target/tentative/anchor.html
+++ /dev/null
@@ -1,109 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-
-<head>
-  <script src="/resources/testharness.js"></script>
-  <script src="/resources/testharnessreport.js"></script>
-  <script src="/resources/testdriver.js"></script>
-  <script src="/resources/testdriver-vendor.js"></script>
-  <script src="/resources/testdriver-actions.js"></script>
-  <script src="/wai-aria/scripts/aria-utils.js"></script>
-  <style>
-    body {
-      margin: 0;
-    }
-
-    [popover] {
-      position: absolute;
-      left: anchor(right);
-      top: anchor(top);
-      margin: 0;
-    }
-  </style>
-</head>
-
-<body>
-  <div>
-    <x-anchor id="x-anchor-1">
-      <template shadowrootmode="open" shadowrootreferencetarget="anchor">
-        <style>
-          div {
-            width: 100px;
-            height: 100px;
-          }
-
-          #anchor {
-            background-color: yellow;
-          }
-        </style>
-
-        <div></div>
-        <div id="anchor"></div>
-      </template>
-    </x-anchor>
-    <div id="popover-1" popover anchor="x-anchor-1">Popover content</div>
-  </div>
-
-  <div>
-    <x-anchor-2 id="x-anchor-2"></x-anchor-2>
-    <div id="popover-2" popover anchor="x-anchor-2">Popover content</div>
-  </div>
-  <script>
-    const customAnchor = document.querySelector('x-anchor-2');
-    customAnchor.attachShadow({ mode: 'open', referenceTarget: 'anchor' });
-    customAnchor.shadowRoot.innerHTML =`
-<style>
-div {
-width: 100px;
-height: 100px;
-}
-
-#anchor {
-background-color: yellow;
-}
-</style>
-
-<div></div>
-<div id="anchor"></div>`;
-  </script>
-
-  <div>
-    <x-anchor id="x-anchor-3">
-      <template shadowrootmode="open" shadowrootreferencetarget="anchor">
-        <style>
-          div {
-            width: 100px;
-            height: 100px;
-          }
-
-          #anchor {
-            background-color: yellow;
-          }
-        </style>
-
-        <div></div>
-        <div id="anchor"></div>
-      </template>
-    </x-anchor>
-    <div id="popover-3" popover>Popover content</div>
-  </div>
-
-  <script>
-    function testPopoverAnchor(id, name) {
-      test(function () {
-        const popover = document.getElementById(id);
-        popover.showPopover();
-        assert_equals(popover.offsetLeft, 100, "popover.offsetLeft");
-        assert_equals(popover.offsetTop, 100, "popover.offsetTop");
-        // Clean up the test context for future tests.
-        popover.parentElement.remove();
-      }, name);
-    }
-    testPopoverAnchor('popover-1', "ShadowRoot ReferenceTarget works with anchor attribute.");
-    testPopoverAnchor('popover-2', "ShadowRoot ReferenceTarget works with anchor attribute via options.");
-    document.getElementById('popover-3').anchorElement = document.getElementById('x-anchor-3');
-    testPopoverAnchor('popover-3', "ShadowRoot ReferenceTarget works with .anchorElement property.");
-  </script>
-</body>
-
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/responsive/animation-on-pseudo-to-display-none.html b/third_party/blink/web_tests/external/wpt/web-animations/responsive/animation-on-pseudo-to-display-none.html
deleted file mode 100644
index 95d39185..0000000
--- a/third_party/blink/web_tests/external/wpt/web-animations/responsive/animation-on-pseudo-to-display-none.html
+++ /dev/null
@@ -1,92 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  <meta name="viewport" content="width=device-width, initial-scale=1">
-  <title>Animation on pseudo to display: none</title>
-  <link rel="help" href="https://www.w3.org/TR/css-animations-2/#owning-element-section">
-  <script src="/resources/testharness.js"></script>
-  <script src="/resources/testharnessreport.js"></script>
-  <style>
-    #target {
-      background-color: lightgoldenrodyellow;
-      height: 100px;
-      width: 100px;
-      position: relative;
-    }
-    @keyframes vanish {
-      to {
-        opacity: 0;
-        display: none;
-      }
-    }
-    #target::before {
-      box-sizing: border-box;
-      content: "hello";
-      position: absolute;
-      top: 0;
-      right: 0;
-      bottom: 0;
-      left: 0;
-    }
-    #target.vanish::before {
-      animation: vanish 1s forwards steps(1, jump-end);
-    }
-
-    #target.label::before {
-      content: "world";
-    }
-
-    #target.hide::before {
-      display: none;
-    }
-
-  </style>
-</head>
-<body>
-  <div id="target"></div>
-</body>
-<script>
-  promise_test(async t => {
-    const target = document.getElementById('target');
-    const opacity = () => {
-      return getComputedStyle(target, '::before').opacity;
-    };
-    const display = () => {
-      return getComputedStyle(target, '::before').display;
-    };
-
-    target.classList.add('vanish');
-    let anim = document.getAnimations()[0];
-    assert_true(!!anim, 'animation created');
-    assert_equals(anim.animationName, 'vanish');
-
-    anim.finish();
-    assert_equals(opacity(), '0', 'opacity when animation is finished');
-    assert_equals(document.getAnimations()[0], anim,
-                   'same animation is still running');
-
-    target.classList.add('label');
-    assert_equals(document.getAnimations().length, 1,
-                  'animation still alive after style update');
-    assert_equals(opacity(), '0', 'opacity after style update');
-
-    target.classList.add('hide');
-    assert_equals(document.getAnimations().length, 0,
-                  'display: none on the base style cancels the animation');
-
-    target.classList.remove('hide');
-    assert_equals(document.getAnimations().length, 1,
-                  'Removing display:none in the base style restarts the ' +
-                  'animation');
-    anim = document.getAnimations()[0];
-    assert_equals(anim.animationName, 'vanish', 'name of restarted animation');
-    assert_equals(opacity(), '1', 'opacity after restart');
-    anim.finish();
-    assert_equals(opacity(), '0', 'opacity after restart and finish');
-    anim.cancel();
-    assert_equals(opacity(), '1', 'opacity after cancel');
-  }, 'display:none via a CSS animation on a pseudo-element does not cancel ' +
-       'the animation.');
-</script>
-</html>
diff --git a/third_party/blink/web_tests/fast/dom/OWNERS b/third_party/blink/web_tests/fast/dom/OWNERS
new file mode 100644
index 0000000..2757923f
--- /dev/null
+++ b/third_party/blink/web_tests/fast/dom/OWNERS
@@ -0,0 +1 @@
+file://third_party/blink/renderer/core/dom/OWNERS
diff --git a/third_party/blink/web_tests/fast/forms/OWNERS b/third_party/blink/web_tests/fast/forms/OWNERS
new file mode 100644
index 0000000..de6f5e00
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/OWNERS
@@ -0,0 +1 @@
+file://third_party/blink/renderer/core/html/forms/OWNERS
diff --git a/third_party/blink/web_tests/fast/html/OWNERS b/third_party/blink/web_tests/fast/html/OWNERS
new file mode 100644
index 0000000..b698fea7
--- /dev/null
+++ b/third_party/blink/web_tests/fast/html/OWNERS
@@ -0,0 +1 @@
+file://third_party/blink/renderer/core/html/OWNERS
diff --git a/third_party/blink/web_tests/html/OWNERS b/third_party/blink/web_tests/html/OWNERS
new file mode 100644
index 0000000..b698fea7
--- /dev/null
+++ b/third_party/blink/web_tests/html/OWNERS
@@ -0,0 +1 @@
+file://third_party/blink/renderer/core/html/OWNERS
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/deprecation-language-model-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/deprecation-language-model-expected.txt
index dc3284c..23a0c54 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/deprecation-language-model-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/deprecation-language-model-expected.txt
@@ -6,8 +6,12 @@
         languageModelExists : true
         languageModelParamsExists : false
         paramsExists : false
+        session1OnContextOverflowExists : true
+        session1OnQuotaOverflowExists : false
         session1TemperatureExists : false
         session1TopKExists : false
+        session2OnContextOverflowExists : true
+        session2OnQuotaOverflowExists : false
         session2TemperatureExists : false
         session2TopKExists : false
     }
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/deprecation-language-model.js b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/deprecation-language-model.js
index a9e56b6..ad556f2 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/deprecation-language-model.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/deprecation-language-model.js
@@ -25,6 +25,8 @@
         results.createWithoutOptionsFailed = false;
         results.session1TopKExists = 'topK' in lmSession1;
         results.session1TemperatureExists = 'temperature' in lmSession1;
+        results.session1OnQuotaOverflowExists = 'onquotaoverflow' in lmSession1
+        results.session1OnContextOverflowExists = 'oncontextoverflow' in lmSession1
       } catch (e) {
         results.createWithoutOptionsFailed = true;
         results.createWithoutOptionsError = e.message;
@@ -36,6 +38,8 @@
         results.createWithOptionsFailed = false;
         results.session2TopKExists = 'topK' in lmSession2;
         results.session2TemperatureExists = 'temperature' in lmSession2;
+        results.session2OnQuotaOverflowExists = 'onquotaoverflow' in lmSession2
+        results.session2OnContextOverflowExists = 'oncontextoverflow' in lmSession2
       } catch (e) {
         results.createWithOptionsFailed = true;
         results.createWithOptionsError = e.message;
diff --git a/third_party/blink/web_tests/inspector-protocol/dom/dom-getAnchorElement.js b/third_party/blink/web_tests/inspector-protocol/dom/dom-getAnchorElement.js
index 422307b..1c8cf476 100644
--- a/third_party/blink/web_tests/inspector-protocol/dom/dom-getAnchorElement.js
+++ b/third_party/blink/web_tests/inspector-protocol/dom/dom-getAnchorElement.js
@@ -4,6 +4,7 @@
   await dp.DOM.enable();
   const getDocumentResponse = await dp.DOM.getDocument();
   const target = (await dp.DOM.querySelector({nodeId: getDocumentResponse.result.root.nodeId, selector: '#target'})).result.nodeId;
+  const target2 = (await dp.DOM.querySelector({nodeId: getDocumentResponse.result.root.nodeId, selector: '#target2'})).result.nodeId;
   const defaultTarget = (await dp.DOM.querySelector({nodeId: getDocumentResponse.result.root.nodeId, selector: '#default-target'})).result.nodeId;
 
   // Get named, implicit, and default anchors via queries.
@@ -21,7 +22,7 @@
   testRunner.log(implicitAnchorByQuery === implicitAnchor.result.nodeId);
   testRunner.log(defaultAnchorByQuery === defaultAnchor.result.nodeId);
 
-  const unreachableAnchor = await dp.DOM.getAnchorElement({nodeId: target, anchorSpecifier: '--unreachable'});
+  const unreachableAnchor = await dp.DOM.getAnchorElement({nodeId: target2, anchorSpecifier: '--unreachable'});
   const nonExistentAnchor = await dp.DOM.getAnchorElement({nodeId: namedAnchorByQuery});
   testRunner.log('Anchor query with no valid result should return node Id of 0:');
   testRunner.log(unreachableAnchor.result.nodeId);
diff --git a/third_party/blink/web_tests/inspector-protocol/dom/resources/dom-get-anchor-element.html b/third_party/blink/web_tests/inspector-protocol/dom/resources/dom-get-anchor-element.html
index e0d35b9..2a3a740 100644
--- a/third_party/blink/web_tests/inspector-protocol/dom/resources/dom-get-anchor-element.html
+++ b/third_party/blink/web_tests/inspector-protocol/dom/resources/dom-get-anchor-element.html
@@ -17,7 +17,7 @@
       anchor-name: --unreachable;
     }
 
-    #target {
+    #target, #target2 {
       position: absolute;
     }
 
@@ -29,11 +29,17 @@
   <body>
     <div class="parent">
       <div id="named-anchor"></div>
-      <div id="implicit-anchor"></div>
+      <button id="implicit-anchor" popovertarget="target"></button>
       <div id="default-anchor"></div>
-      <div id="target" anchor="implicit-anchor"></div>
+      <div id="target" popover></div>
       <div id="default-target"></div>
+      <div id="target2"></div>
     </div>
     <div id="unreachable-anchor"></div>
+    <script>
+      const implicitAnchor = document.getElementById('implicit-anchor');
+      const target = document.getElementById('target');
+      target.showPopover({source: implicitAnchor});
+    </script>
   </body>
 </html>
diff --git a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/README.md b/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/README.md
deleted file mode 100644
index d3841b1..0000000
--- a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Overview
-
-This suite tests with `--disable-blink-features=HTMLAnchorAttribute`.
-
diff --git a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-anchor-idl-property.tentative-expected.txt b/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-anchor-idl-property.tentative-expected.txt
deleted file mode 100644
index a6dfea0..0000000
--- a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-anchor-idl-property.tentative-expected.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] popover anchorElement IDL property returns the anchor element
-  assert_equals: expected (object) Element node <button id="b1">This is an anchor button</button> but got (undefined) undefined
-[FAIL] popover anchorElement is settable
-  assert_equals: expected (object) Element node <button id="b1">This is an anchor button</button> but got (undefined) undefined
-[FAIL] anchorElement affects anchor positioning
-  assert_equals: expected (object) null but got (undefined) undefined
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-anchor-multicol-display.tentative-expected.txt b/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-anchor-multicol-display.tentative-expected.txt
deleted file mode 100644
index 50c9b1dd..0000000
--- a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-anchor-multicol-display.tentative-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] .target 1
-  assert_equals: \n<div class="target" popover="" anchor="anchor1" data-expected-height="30"></div>\nheight expected 30 but got 20
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-light-dismiss-with-anchor.tentative-expected.txt b/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-light-dismiss-with-anchor.tentative-expected.txt
deleted file mode 100644
index bc3c868..0000000
--- a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-light-dismiss-with-anchor.tentative-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] Clicking inside a child popover shouldn't close either popover
-  assert_true: popover1 should be open expected true got false
-[FAIL] Clicking inside a parent popover should close child popover
-  assert_true: expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-shadow-dom-anchor.tentative-expected.txt b/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-shadow-dom-anchor.tentative-expected.txt
deleted file mode 100644
index 348fd75..0000000
--- a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-shadow-dom-anchor.tentative-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] anchor references use the flat tree not the DOM tree
-  assert_true: expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-stacking-anchor-attribute.tentative-expected.txt b/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-stacking-anchor-attribute.tentative-expected.txt
deleted file mode 100644
index ac87b4c..0000000
--- a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-stacking-anchor-attribute.tentative-expected.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] anchor attribute relationship
-  assert_true: expected true got false
-[FAIL] indirect anchor attribute relationship
-  assert_true: expected true got false
-[FAIL] more complex nesting, all using anchor ancestry
-  assert_equals: Popover #1 incorrect state expected true but got false
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-top-layer-nesting-anchor.tentative-expected.txt b/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-top-layer-nesting-anchor.tentative-expected.txt
deleted file mode 100644
index 98bfdb2..0000000
--- a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-top-layer-nesting-anchor.tentative-expected.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] Single popover=auto ancestor with dialog, anchor attribute
-  assert_equals: Incorrect behavior expected true but got false
-[FAIL] Single popover=auto ancestor with fullscreen, anchor attribute
-  assert_equals: Incorrect behavior expected true but got false
-[FAIL] Single popover=manual ancestor with dialog, anchor attribute
-  assert_equals: Incorrect behavior expected true but got false
-[FAIL] Single popover=manual ancestor with fullscreen, anchor attribute
-  assert_equals: Incorrect behavior expected true but got false
-[FAIL] Nested popover=auto ancestors with dialog, anchor attribute
-  assert_equals: Incorrect behavior expected true but got false
-[FAIL] Nested popover=auto ancestors with fullscreen, anchor attribute
-  assert_equals: Incorrect behavior expected true but got false
-[FAIL] Nested popover=auto ancestors, target is outer with dialog, anchor attribute
-  assert_equals: Incorrect behavior expected true but got false
-[FAIL] Nested popover=auto ancestors, target is outer with fullscreen, anchor attribute
-  assert_equals: Incorrect behavior expected true but got false
-[FAIL] Top layer inside of nested element with dialog, anchor attribute
-  assert_equals: Incorrect behavior expected true but got false
-[FAIL] Top layer inside of nested element with fullscreen, anchor attribute
-  assert_equals: Incorrect behavior expected true but got false
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-types-with-hints-and-anchor.tentative-expected.txt b/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-types-with-hints-and-anchor.tentative-expected.txt
deleted file mode 100644
index dcfa3b3..0000000
--- a/third_party/blink/web_tests/virtual/html-anchor-attribute-disabled/external/wpt/html/semantics/popovers/popover-types-with-hints-and-anchor.tentative-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] hint is not closed by pre-existing auto
-  assert_equals: Error, index 2 (<div popover="">popover 3</div>) expected false but got true
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/webui-browser/external/wpt/html/browsers/windows/nested-browsing-contexts/window-top-expected.txt b/third_party/blink/web_tests/virtual/webui-browser/external/wpt/html/browsers/windows/nested-browsing-contexts/window-top-expected.txt
deleted file mode 100644
index aa961c1..0000000
--- a/third_party/blink/web_tests/virtual/webui-browser/external/wpt/html/browsers/windows/nested-browsing-contexts/window-top-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = element not interactable\n  (Session info: chrome=147.0.7701.0)\nTraceback (most recent call last):\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 1186, in run_func\n    self.result = True, self.func(self.protocol, self.url, self.timeout)\n                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 1275, in do_testharness\n    test_window = self.create_test_window(protocol)\n                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py", line 356, in create_test_window\n    test_window = super().create_test_window(protocol)\n                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 1325, in create_test_window\n    protocol.click.element(selector)\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py", line 579, in element\n    return element.click()\n           ^^^^^^^^^^^^^^^\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 904, in click\n    self.send_element_command("POST", "click", {})\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 897, in send_element_command\n    return self.session.send_session_command(method, url, body)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 650, in send_session_command\n    return self.send_command(method, url, body, timeout)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File "/b/s/w/ir/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py", line 605, in send_command\n    raise err\nwebdriver.error.WebDriverException: element not interactable (400): element not interactable\n  (Session info: chrome=147.0.7701.0)\n\nRemote-end stacktrace:\n\n#0 0x55c9e1208132 <unknown>\n#1 0x55c9e11f2e31 <unknown>\n#2 0x55c9e08209eb <unknown>\n#3 0x55c9e0876e98 <unknown>\n#4 0x55c9e086c424 <unknown>\n#5 0x55c9e086bddf <unknown>\n#6 0x55c9e086bcb2 <unknown>\n#7 0x55c9e08c613f <unknown>\n#8 0x55c9e08c59b4 <unknown>\n#9 0x55c9e086ab4d <unknown>\n#10 0x55c9e0869539 <unknown>\n#11 0x55c9e086a72a <unknown>\n#12 0x55c9e0800391 <unknown>\n#13 0x55c9e1159f11 <unknown>\n#14 0x55c9e1192bde <unknown>\n#15 0x55c9e119200b <unknown>\n#16 0x55c9e1172c06 <unknown>\n#17 0x55c9e1193d1a <unknown>\n#18 0x55c9e11447d6 <unknown>\n#19 0x55c9e11d76c6 <unknown>\n#20 0x55c9e11d7af7 <unknown>\n#21 0x55c9e11f0d83 <unknown>\n#22 0x72fad9894ac3 <unknown>\n#23 0x72fad99268d0 <unknown>\n
-Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
index 74948d23..3d25eeb 100644
--- a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
@@ -28,10 +28,13 @@
     property activeViewTransition
     property addEventListener
     property after
-    property anchorElement
+    property afterHTML
+    property afterHTMLUnsafe
     property animate
     property append
     property appendChild
+    property appendHTML
+    property appendHTMLUnsafe
     property ariaActiveDescendantElement
     property ariaAtomic
     property ariaAutoComplete
@@ -94,6 +97,8 @@
     property autofocus
     property baseURI
     property before
+    property beforeHTML
+    property beforeHTMLUnsafe
     property blur
     property checkVisibility
     property childElementCount
@@ -310,6 +315,8 @@
     property popover
     property prefix
     property prepend
+    property prependHTML
+    property prependHTMLUnsafe
     property previousElementSibling
     property previousSibling
     property pseudo
@@ -325,6 +332,8 @@
     property replaceChild
     property replaceChildren
     property replaceWith
+    property replaceWithHTML
+    property replaceWithHTMLUnsafe
     property requestFullscreen
     property requestPointerLock
     property role
@@ -350,7 +359,9 @@
     property slot
     property spellcheck
     property startViewTransition
+    property streamAppendHTML
     property streamAppendHTMLUnsafe
+    property streamHTML
     property streamHTMLUnsafe
     property style
     property tabIndex
@@ -1365,10 +1376,13 @@
     property activeViewTransition
     property addEventListener
     property after
-    property anchorElement
+    property afterHTML
+    property afterHTMLUnsafe
     property animate
     property append
     property appendChild
+    property appendHTML
+    property appendHTMLUnsafe
     property ariaActiveDescendantElement
     property ariaAtomic
     property ariaAutoComplete
@@ -1429,6 +1443,8 @@
     property autofocus
     property baseURI
     property before
+    property beforeHTML
+    property beforeHTMLUnsafe
     property blur
     property checkVisibility
     property childElementCount
@@ -1626,6 +1642,8 @@
     property part
     property prefix
     property prepend
+    property prependHTML
+    property prependHTMLUnsafe
     property previousElementSibling
     property previousSibling
     property pseudo
@@ -1641,6 +1659,8 @@
     property replaceChild
     property replaceChildren
     property replaceWith
+    property replaceWithHTML
+    property replaceWithHTMLUnsafe
     property requestFullscreen
     property requestPointerLock
     property role
@@ -1663,7 +1683,9 @@
     property shadowRoot
     property slot
     property startViewTransition
+    property streamAppendHTML
     property streamAppendHTMLUnsafe
+    property streamHTML
     property streamHTMLUnsafe
     property style
     property tabIndex
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 1a9e2e2c9..5c7bc32 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -1430,14 +1430,20 @@
     getter nextElementSibling
     getter previousElementSibling
     method after
+    method afterHTML
+    method afterHTMLUnsafe
     method appendData
     method before
+    method beforeHTML
+    method beforeHTMLUnsafe
     method constructor
     method deleteData
     method insertData
     method remove
     method replaceData
     method replaceWith
+    method replaceWithHTML
+    method replaceWithHTMLUnsafe
     method substringData
     setter data
 interface Clipboard : EventTarget
@@ -2403,10 +2409,16 @@
     getter publicId
     getter systemId
     method after
+    method afterHTML
+    method afterHTMLUnsafe
     method before
+    method beforeHTML
+    method beforeHTMLUnsafe
     method constructor
     method remove
     method replaceWith
+    method replaceWithHTML
+    method replaceWithHTMLUnsafe
 interface DragEvent : MouseEvent
     attribute @@toStringTag
     getter dataTransfer
@@ -2448,7 +2460,6 @@
     attribute @@toStringTag
     attribute @@unscopables
     getter activeViewTransition
-    getter anchorElement
     getter ariaActiveDescendantElement
     getter ariaAtomic
     getter ariaAutoComplete
@@ -2549,11 +2560,17 @@
     getter slot
     getter tagName
     method after
+    method afterHTML
+    method afterHTMLUnsafe
     method animate
     method append
+    method appendHTML
+    method appendHTMLUnsafe
     method ariaNotify
     method attachShadow
     method before
+    method beforeHTML
+    method beforeHTMLUnsafe
     method checkVisibility
     method closest
     method computedStyleMap
@@ -2580,6 +2597,8 @@
     method matches
     method moveBefore
     method prepend
+    method prependHTML
+    method prependHTMLUnsafe
     method pseudo
     method querySelector
     method querySelectorAll
@@ -2590,6 +2609,8 @@
     method removeAttributeNode
     method replaceChildren
     method replaceWith
+    method replaceWithHTML
+    method replaceWithHTMLUnsafe
     method requestFullscreen
     method requestPointerLock
     method scroll
@@ -2605,13 +2626,14 @@
     method setHTMLUnsafe
     method setPointerCapture
     method startViewTransition
+    method streamAppendHTML
     method streamAppendHTMLUnsafe
+    method streamHTML
     method streamHTMLUnsafe
     method toggleAttribute
     method webkitMatchesSelector
     method webkitRequestFullScreen
     method webkitRequestFullscreen
-    setter anchorElement
     setter ariaActiveDescendantElement
     setter ariaAtomic
     setter ariaAutoComplete
@@ -5890,7 +5912,7 @@
     attribute @@toStringTag
     getter contextUsage
     getter contextWindow
-    getter onquotaoverflow
+    getter oncontextoverflow
     method append
     method clone
     method constructor
@@ -5898,7 +5920,7 @@
     method measureContextUsage
     method prompt
     method promptStreaming
-    setter onquotaoverflow
+    setter oncontextoverflow
 interface LanguageModelToolCall
     attribute @@toStringTag
     getter arguments
@@ -9871,15 +9893,21 @@
     getter serializable
     getter slotAssignment
     getter styleSheets
+    method appendHTML
+    method appendHTMLUnsafe
     method constructor
     method elementFromPoint
     method elementsFromPoint
     method getAnimations
     method getHTML
     method getSelection
+    method prependHTML
+    method prependHTMLUnsafe
     method setHTML
     method setHTMLUnsafe
+    method streamAppendHTML
     method streamAppendHTMLUnsafe
+    method streamHTML
     method streamHTMLUnsafe
     setter adoptedStyleSheets
     setter fullscreenElement
diff --git a/third_party/boringssl/src b/third_party/boringssl/src
index 7d88bb1..626a257 160000
--- a/third_party/boringssl/src
+++ b/third_party/boringssl/src
@@ -1 +1 @@
-Subproject commit 7d88bb1bf3372bda1134ad8bf624b25b88e0db86
+Subproject commit 626a2578ac3e2840d4664562de39d25b1e710a19
diff --git a/third_party/catapult b/third_party/catapult
index 9fdb1d4..1ec5864 160000
--- a/third_party/catapult
+++ b/third_party/catapult
@@ -1 +1 @@
-Subproject commit 9fdb1d4c9d0f278ae34891b069d96ef89ea9cdf2
+Subproject commit 1ec586469aedb45f1e0809017409346ddf96e210
diff --git a/third_party/closure_compiler/externs/tabs.js b/third_party/closure_compiler/externs/tabs.js
index c74a97a..6530047 100644
--- a/third_party/closure_compiler/externs/tabs.js
+++ b/third_party/closure_compiler/externs/tabs.js
@@ -1,4 +1,4 @@
-// Copyright 2025 The Chromium Authors
+// Copyright 2026 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -208,8 +208,7 @@
 chrome.tabs.sendRequest = function(tabId, request, callback) {};
 
 /**
- * Sends a single message to the content script(s) in the specified tab, with an
- * optional callback to run when a response is sent back.  The
+ * Sends a single message to the content script(s) in the specified tab. The
  * $(ref:runtime.onMessage) event is fired in each content script running in the
  * specified tab for the current extension.
  * @param {number} tabId
@@ -219,7 +218,9 @@
  *   frameId: (number|undefined),
  *   documentId: (string|undefined)
  * }=} options
- * @param {function(*): void=} callback
+ * @param {function(*): void=} callback Promise that resolves with the response
+ *     from the content script. If an error occurs while connecting to the
+ *     specified tab, the promise will be rejected.
  * @see https://developer.chrome.com/extensions/tabs#method-sendMessage
  */
 chrome.tabs.sendMessage = function(tabId, message, options, callback) {};
diff --git a/third_party/dawn b/third_party/dawn
index d21eb9f..67a0164 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit d21eb9f4c686880e65d8e6c94e8b0596b09ac435
+Subproject commit 67a0164c434f43952232554ed1f90369206ff5d1
diff --git a/third_party/depot_tools b/third_party/depot_tools
index 8aad286..044f01a 160000
--- a/third_party/depot_tools
+++ b/third_party/depot_tools
@@ -1 +1 @@
-Subproject commit 8aad2863865f0d0bde8b2eb804b389412f04a38b
+Subproject commit 044f01ae0351fb8a97efce042c93f99d3e95240c
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index cf41280..a718fd5 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit cf4128082e46865c4469211511703c4d4d76ed33
+Subproject commit a718fd59205c847882992a8aec65f5e23ed93a7c
diff --git a/third_party/eigen3/src b/third_party/eigen3/src
index c4c704e..d0d70a9 160000
--- a/third_party/eigen3/src
+++ b/third_party/eigen3/src
@@ -1 +1 @@
-Subproject commit c4c704e5ddca35c10cca625807a6919654753459
+Subproject commit d0d70a952766f6b02f449da040141529748ecd30
diff --git a/third_party/ink_stroke_modeler/README.chromium b/third_party/ink_stroke_modeler/README.chromium
index 1410427b..5e363c2 100644
--- a/third_party/ink_stroke_modeler/README.chromium
+++ b/third_party/ink_stroke_modeler/README.chromium
@@ -1,7 +1,7 @@
 Name: Ink Stroke Modeler
 URL: https://github.com/google/ink-stroke-modeler
 Version: N/A
-Revision: eb42ec75e79ebde11169519e8c665a8f0c4e1fc3
+Revision: 3fa5129ed1ae6f8b2ec4e9b60fa5d08cc81e2d78
 Update Mechanism: Autoroll
 License: Apache-2.0
 License File: LICENSE
diff --git a/third_party/ink_stroke_modeler/src b/third_party/ink_stroke_modeler/src
index eb42ec7..3fa5129e 160000
--- a/third_party/ink_stroke_modeler/src
+++ b/third_party/ink_stroke_modeler/src
@@ -1 +1 @@
-Subproject commit eb42ec75e79ebde11169519e8c665a8f0c4e1fc3
+Subproject commit 3fa5129ed1ae6f8b2ec4e9b60fa5d08cc81e2d78
diff --git a/third_party/jni_zero/README.chromium.md b/third_party/jni_zero/README.chromium.md
index 179820d..7d4e3f9f 100644
--- a/third_party/jni_zero/README.chromium.md
+++ b/third_party/jni_zero/README.chromium.md
@@ -79,17 +79,18 @@
 std::string JNI_MyClass_GetName(JNIEnv* env) { return "name"; }
 ```
 
-**Header:** `#include "base/android/jni_string.h"`
 **Null Handling:** `null` Java strings are converted to empty `std::string` or `std::u16string`.
 
 ### Callbacks (Java -> Native)
 
-To pass a Java `Runnable` or `Callback` to C++ as a `base::OnceClosure` or `base::OnceCallback`.
+* To pass a Java `Runnable` / `Callback` / `Callback2` to C++ as a `base::OnceCallback`, use `@JniType`.
+* 3+ or more parameter variants is not currently supported.
 
 **Java:**
 ```java
 void doSomething(@JniType("base::OnceClosure") Runnable callback);
 void fetchSuccess(@JniType("base::OnceCallback<void(std::string)>") Callback<String> callback);
+void fetchSuccess2(@JniType("base::OnceCallback<void(const jni_zero::JavaRef<jobject>&, long)>") Callback2<SomeClass, Long> callback);
 ```
 
 **C++:**
@@ -100,17 +101,22 @@
 void JNI_MyClass_DoSomething(JNIEnv* env, base::OnceClosure callback) {
     std::move(callback).Run();
 }
-```
 
-**Header:** `#include "base/android/callback_android.h"`
+void JNI_MyClass_FetchSuccess2(JNIEnv* env, base::OnceCallback<void(const jni_zero::JavaRef<jobject>&, long)> callback) {
+    std::move(callback).Run(nullptr, 123L);
+}
+```
 
 ### Callbacks (Native -> Java)
 
-To pass a C++ callback to Java, use `@JniType` on the Java side. The Java side should
-receive a `JniOnceCallback<T>`, `JniRepeatingCallback<T>`, `JniOnceRunnable`, or
-`JniRepeatingRunnable` (which for the `Once*` variants, can be typed as
-`Runnable` or `Callback` if you don't need to call `destroy()`). For two-parameter
-callbacks, use `Callback2<T1, T2>`.
+* To pass a C++ callback to Java, use `@JniType` on the Java side.
+* The Java side may be typed one of:
+  * `JniOnceRunnable` / `JniRepeatingRunnable`
+  * `JniOnceCallback<T>` / `JniRepeatingCallback<T>`,
+  * `JniOnceCallback2<T1, T2>` / `JniRepeatingCallback2<T1. T2>`,
+* For the `Repeating*` variants, you must call `destroy()` when done with them.
+* For the `Once*` variants, `destroy()` is called when it's run, but you must call it manually if it is never run.
+* The `Once*` variants, can be typed as `Runnable` / `Callback` / `Callback2` if you don't need `destroy()`.
 
 **Java:**
 ```java
@@ -120,6 +126,11 @@
 }
 
 @CalledByNative
+void onResult2(@JniType("base::OnceCallback<void(const jni_zero::JavaRef<jobject>&, long)>") JniOnceCallback2<SomeClass, Long> callback) {
+    callback.onResult(new SomeClass(), 123L);
+}
+
+@CalledByNative
 @JniType("base::OnceClosure")
 Runnable getClosure();
 ```
@@ -133,6 +144,13 @@
     Java_MyClass_onResult(env, std::move(callback));
 }
 
+void Finish2(JNIEnv* env, base::OnceCallback<void(const jni_zero::JavaRef<jobject>&, long)> callback) {
+    auto callback = base::BindOnce([](){
+      ...
+    });
+    Java_MyClass_onResult2(env, std::move(callback));
+}
+
 base::OnceClosure JNI_MyClass_GetClosure(JNIEnv* env) {
     return base::BindOnce([](){
       ...
@@ -140,13 +158,6 @@
 }
 ```
 
-**Header:** `#include "base/android/callback_android.h"`
-
-**Important:** For the `Once*` variants, you must call `destroy()` on the Java
-callback if it is never run to avoid leaking the native object.
-`JniOnceCallback` and `JniOnceRunnable` will automatically destroy themselves
-after one call. For the `Repeating*` variants, you must call `destroy()` when
-done with them.
 
 ### Nullable Parameters (std::optional)
 
diff --git a/third_party/jni_zero/common_apis.h b/third_party/jni_zero/common_apis.h
index 12136d4..25bd559 100644
--- a/third_party/jni_zero/common_apis.h
+++ b/third_party/jni_zero/common_apis.h
@@ -48,9 +48,9 @@
     const JavaRef<jobject>& list,
     int32_t idx,
     const JavaRef<jobject>& value);
-// Use ToJniType on the value.
+// Helper that calls ToJniType on the value before calling ListSet.
 template <typename V>
-  requires(!internal::IsJavaRef<V>)
+  requires(!IsJavaRef<V>)
 inline ScopedJavaLocalRef<jobject> ListSet(JNIEnv* env,
                                            const JavaRef<jobject>& list,
                                            int32_t idx,
@@ -65,9 +65,9 @@
     JNIEnv* env,
     const JavaRef<jobject>& collection,
     const JavaRef<jobject>& value);
-// Use ToJniType on the value.
+// Helper that calls ToJniType on the value before calling CollectionAdd.
 template <typename V>
-  requires(!internal::IsJavaRef<V>)
+  requires(!IsJavaRef<V>)
 inline ScopedJavaLocalRef<jobject>
 CollectionAdd(JNIEnv* env, const JavaRef<jobject>& collection, const V& value) {
   return CollectionAdd(env, collection, ToJniType(env, value));
@@ -103,9 +103,9 @@
     const JavaRef<jobject>& key,
     const JavaRef<jobject>& value);
 
-// Use ToJniType on the key/value.
+// Helper that calls ToJniType on the key and value before calling MapPut.
 template <typename K, typename V>
-  requires(!internal::IsJavaRef<K> && !internal::IsJavaRef<V>)
+  requires(!IsJavaRef<K> || !IsJavaRef<V>)
 inline ScopedJavaLocalRef<jobject> MapPut(JNIEnv* env,
                                           const JavaRef<jobject>& map,
                                           const K& key,
diff --git a/third_party/jni_zero/default_conversions.h b/third_party/jni_zero/default_conversions.h
index 3a310bf..8dcee470 100644
--- a/third_party/jni_zero/default_conversions.h
+++ b/third_party/jni_zero/default_conversions.h
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// FromJniType / ToJniType conversions that are not #included from jni_zero.h
+// (and are thus optional).
 #ifndef JNI_ZERO_DEFAULT_CONVERSIONS_H_
 #define JNI_ZERO_DEFAULT_CONVERSIONS_H_
 
@@ -15,7 +17,8 @@
 
 namespace jni_zero {
 
-// Allow conversions using std::optional by wrapping non-optional conversions.
+// Conversion from a Java object to a std::optional.
+// A null Java reference results in std::nullopt.
 template <internal::IsOptional T>
 inline T FromJniType(JNIEnv* env, const JavaRef<jobject>& j_object) {
   if (!j_object) {
@@ -24,6 +27,8 @@
   return FromJniType<typename T::value_type>(env, j_object);
 }
 
+// Conversion from a std::optional to a Java object.
+// std::nullopt results in a null Java reference.
 template <internal::IsOptional T>
 inline ScopedJavaLocalRef<jobject> ToJniType(JNIEnv* env, const T& opt_value) {
   if (!opt_value) {
@@ -176,7 +181,8 @@
   return ArrayToList(env, arr);
 }
 
-// Convert Map -> stl map type using FromJniType() on each key & value.
+// Convert a Java Map to a C++ map-like container.
+// Calls FromJniType for each key and value.
 template <internal::IsMap ContainerType>
 inline ContainerType FromJniType(JNIEnv* env,
                                  const JavaRef<jobject>& j_object) {
@@ -197,15 +203,14 @@
     jobject j_key = env->GetObjectArrayElement(j_array.obj(), i);
     jobject j_value = env->GetObjectArrayElement(j_array.obj(), i + 1);
     // Do not call FromJni for jobject->jobject.
-    if constexpr (internal::IsJavaRef<KeyType> &&
-                  internal::IsJavaRef<ValueType>) {
+    if constexpr (IsJavaRef<KeyType> && IsJavaRef<ValueType>) {
       ret.emplace(std::piecewise_construct, std::forward_as_tuple(env, j_key),
                   std::forward_as_tuple(env, j_value));
-    } else if constexpr (internal::IsJavaRef<KeyType>) {
+    } else if constexpr (IsJavaRef<KeyType>) {
       auto value = ScopedJavaLocalRef<jobject>::Adopt(env, j_value);
       ret.emplace(std::piecewise_construct, std::forward_as_tuple(env, j_key),
                   FromJniType<ValueType>(env, value));
-    } else if constexpr (internal::IsJavaRef<ValueType>) {
+    } else if constexpr (IsJavaRef<ValueType>) {
       auto key = ScopedJavaLocalRef<jobject>::Adopt(env, j_key);
       ret.emplace(std::piecewise_construct, FromJniType<KeyType>(env, key),
                   std::forward_as_tuple(env, j_value));
@@ -219,7 +224,8 @@
   return ret;
 }
 
-// Convert stl map -> Map type using ToJniType() on each key & value.
+// Convert a C++ map-like container to a Java Map.
+// Calls ToJniType for each key and value.
 template <internal::IsMap ContainerType>
 inline ScopedJavaLocalRef<jobject> ToJniType(JNIEnv* env,
                                              const ContainerType& map) {
@@ -236,7 +242,7 @@
   jsize i = 0;
   for (auto const& [key, value] : map) {
     // Do not call ToJni for jobject->jobject.
-    if constexpr (internal::IsJavaRef<KeyType>) {
+    if constexpr (IsJavaRef<KeyType>) {
       env->SetObjectArrayElement(j_array, i, key.obj());
     } else {
       ScopedJavaLocalRef<jobject> j_key = ToJniType(env, key);
@@ -244,7 +250,7 @@
     }
     ++i;
 
-    if constexpr (internal::IsJavaRef<ValueType>) {
+    if constexpr (IsJavaRef<ValueType>) {
       env->SetObjectArrayElement(j_array, i, value.obj());
     } else {
       ScopedJavaLocalRef<jobject> j_value = ToJniType(env, value);
@@ -256,6 +262,8 @@
   return ArrayToMap(env, array);
 }
 
+// Specializations for primitive types to handle their Java boxed equivalents.
+
 template <>
 inline bool FromJniType<bool>(JNIEnv* env, const JavaRef<jobject>& val) {
   return FromJavaBoolean(env, val);
diff --git a/third_party/jni_zero/java_refs.h b/third_party/jni_zero/java_refs.h
index 2bf84a1..a9a659c1 100644
--- a/third_party/jni_zero/java_refs.h
+++ b/third_party/jni_zero/java_refs.h
@@ -53,6 +53,10 @@
   requires internal::IsJobject<T>
 class JavaRef;
 
+template <typename T>
+concept IsJavaRef =
+    std::is_base_of_v<jni_zero::JavaRef<jobject>, std::remove_cvref_t<T>>;
+
 namespace internal {
 // Create an instance of JavaRef<T> without DCHECK'ing that it is a local ref.
 // Should only be used by the JNI Zero code generator.
@@ -501,6 +505,21 @@
 using JavaParamRef = JavaRef<T>;
 #endif
 
+// Identity overload for FromJniType when the destination type is already a
+// JavaRef.
+template <typename T>
+  requires IsJavaRef<T>
+inline T FromJniType(JNIEnv* env, const JavaRef<jobject>& obj) {
+  return static_cast<T>(obj);
+}
+
+// Identity overload for ToJniType when the input type is already a JavaRef.
+template <typename T>
+  requires IsJavaRef<T>
+inline decltype(auto) ToJniType(JNIEnv* env, T&& arg) {
+  return std::forward<T>(arg);
+}
+
 }  // namespace jni_zero
 
 #endif  // JNI_ZERO_JAVA_REFS_H_
diff --git a/third_party/jni_zero/type_conversions.h b/third_party/jni_zero/type_conversions.h
index 7ad29fa..a7045269 100644
--- a/third_party/jni_zero/type_conversions.h
+++ b/third_party/jni_zero/type_conversions.h
@@ -4,6 +4,7 @@
 
 // IWYU pragma: private, include "third_party/jni_zero/jni_zero.h"
 
+// FromJniType / ToJniType conversions that are #included from jni_zero.h
 #ifndef JNI_ZERO_TYPE_CONVERSIONS_H_
 #define JNI_ZERO_TYPE_CONVERSIONS_H_
 
@@ -27,8 +28,6 @@
   "_jni.h one."
 
 namespace internal {
-template <typename T>
-concept IsJavaRef = std::is_base_of_v<JavaRef<jobject>, T>;
 
 template <typename T>
 concept HasReserve = requires(T t) { t.reserve(0); };
@@ -77,7 +76,7 @@
 template <typename T>
 concept HasSpecificSpecialization = requires(T t) {
   requires IsMap<T> || IsObjectContainer<T> || IsOptional<T> ||
-               IsPrimitive<T> || IsJavaRef<T>;
+               IsPrimitive<T> || jni_zero::IsJavaRef<T>;
 };
 
 // Used to allow for the c++ type to be non-primitive even if the java type is
@@ -104,31 +103,27 @@
 
 }  // namespace internal
 
+// Base template that is resolved only when other specializations are missing.
 template <typename T>
 inline T FromJniType(JNIEnv* env, const JavaRef<jobject>& obj) {
   static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("FromJniType"));
 }
 
+// Base template that is resolved only when other specializations are missing.
 template <typename T>
   requires(!internal::HasSpecificSpecialization<T>)
 inline ScopedJavaLocalRef<jobject> ToJniType(JNIEnv* env, const T& obj) {
   static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniType"));
 }
 
+// Overload of ToJniType for primitive types. This is usually specialized in
+// default_conversions.h to wrap them in their Java boxed equivalents.
 template <typename T>
   requires internal::IsPrimitive<T>
 inline ScopedJavaLocalRef<jobject> ToJniType(JNIEnv* env, T obj) {
   static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniType"));
 }
 
-template <typename T>
-  requires(internal::IsJavaRef<T>)
-inline ScopedJavaLocalRef<jobject> ToJniType(JNIEnv* env, const T& val) {
-  // Might want to change this to an identity function, but maybe it's useful
-  // for catching coding errors?
-  static_assert(sizeof(T) == 0, "Type does not require conversion.");
-}
-
 // Allow conversions using pointers by wrapping non-pointer conversions.
 // Cannot live in default_conversions.h because we want code to be able to
 // specialize it.
@@ -150,8 +145,7 @@
   "If this error is from a non-generated call, ensure that there "       \
   "exists an #include for jni_zero/default_conversions.h."
 
-// Convert from an stl container to a Java array. Uses ToJniType() on each
-// element.
+// Base template that is resolved only when other specializations are missing.
 template <typename T>
 inline ScopedJavaLocalRef<jobjectArray> ToJniArray(JNIEnv* env,
                                                    const T& obj,
@@ -159,28 +153,25 @@
   static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniArray"));
 }
 
-// Convert from a Java array to an stl container of primitive types.
+// Base template that is resolved only when other specializations are missing.
 template <typename T>
 inline ScopedJavaLocalRef<jarray> ToJniArray(JNIEnv* env, const T& obj) {
   static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniArray"));
 }
 
-// Convert from a Java array to an stl container. Uses FromJniType() on each
-// element for non-primitive types.
+// Base template that is resolved only when other specializations are missing.
 template <typename T>
 inline T FromJniArray(JNIEnv* env, const JavaRef<jobject>& obj) {
   static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("FromJniArray"));
 }
 
-// Convert from an stl container to a Java List<> by using ToJniType() on each
-// element.
+// Base template that is resolved only when other specializations are missing.
 template <typename T>
 inline ScopedJavaLocalRef<jobject> ToJniList(JNIEnv* env, const T& obj) {
   static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniList"));
 }
 
-// Convert from a Java Collection<> to an stl container by using FromJniType()
-// on each element.
+// Base template that is resolved only when other specializations are missing.
 template <typename T>
 inline T FromJniCollection(JNIEnv* env, const JavaRef<jobject>& obj) {
   static_assert(sizeof(T) == 0,
@@ -188,6 +179,14 @@
 }
 #undef JNI_ZERO_CONVERSION_FAILED_MSG
 
+// Handles non-JavaRef types that are passed by reference or have cv-qualifiers
+// by decaying them to their base type and calling the base FromJniType.
+template <typename T>
+  requires(!IsJavaRef<T> && !std::is_same_v<T, std::decay_t<T>>)
+inline auto FromJniType(JNIEnv* env, const JavaRef<jobject>& obj) {
+  return FromJniType<std::decay_t<T>>(env, obj);
+}
+
 }  // namespace jni_zero
 
 #endif  // JNI_ZERO_TYPE_CONVERSIONS_H_
diff --git a/third_party/perfetto b/third_party/perfetto
index ea8d0aa..c9609d1 160000
--- a/third_party/perfetto
+++ b/third_party/perfetto
@@ -1 +1 @@
-Subproject commit ea8d0aaeb1e22f03fa0498c42e3f86f3daf753f2
+Subproject commit c9609d1e65bcd21014a708c0c8b8df094cd89a0b
diff --git a/third_party/rust/chromium_crates_io/gnrt_config.toml b/third_party/rust/chromium_crates_io/gnrt_config.toml
index 477d9a8..d1de47f 100644
--- a/third_party/rust/chromium_crates_io/gnrt_config.toml
+++ b/third_party/rust/chromium_crates_io/gnrt_config.toml
@@ -722,6 +722,7 @@
 allow_unsafe = true
 
 [crate.windows-link]
+extra_input_roots = ['../readme.md']
 extra_kv = { allow_unsafe = false }
 
 [crate.windows-sys.extra_kv]
diff --git a/third_party/rust/windows_link/v0_2/BUILD.gn b/third_party/rust/windows_link/v0_2/BUILD.gn
index e37fb13..44a77524 100644
--- a/third_party/rust/windows_link/v0_2/BUILD.gn
+++ b/third_party/rust/windows_link/v0_2/BUILD.gn
@@ -17,7 +17,7 @@
   sources = [
     "//third_party/rust/chromium_crates_io/vendor/windows-link-v0_2/src/lib.rs",
   ]
-  inputs = []
+  inputs = [ "//third_party/rust/chromium_crates_io/vendor/windows-link-v0_2/src/../readme.md" ]
 
   build_native_rust_unit_tests = false
   edition = "2021"
diff --git a/third_party/tflite/README.chromium b/third_party/tflite/README.chromium
index b981224..ba7e529 100644
--- a/third_party/tflite/README.chromium
+++ b/third_party/tflite/README.chromium
@@ -1,9 +1,9 @@
 Name: TensorFlow Lite
 Short Name: tflite
 URL: https://github.com/tensorflow/tensorflow
-Version: 38dd09551686ad00bc837f383b3a1db282079498
-Revision: 38dd09551686ad00bc837f383b3a1db282079498
-Date: 2026-02-17
+Version: 204f897f9a511e62242fcbaac6be5fbbe9e2e245
+Revision: 204f897f9a511e62242fcbaac6be5fbbe9e2e245
+Date: 2026-02-25
 Update Mechanism: Manual
 License: Caffe, Apache-2.0
 License File: LICENSE
diff --git a/third_party/tflite/src b/third_party/tflite/src
index 38dd095..204f897 160000
--- a/third_party/tflite/src
+++ b/third_party/tflite/src
@@ -1 +1 @@
-Subproject commit 38dd09551686ad00bc837f383b3a1db282079498
+Subproject commit 204f897f9a511e62242fcbaac6be5fbbe9e2e245
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps
index 911e009..d3db3d1 160000
--- a/third_party/vulkan-deps
+++ b/third_party/vulkan-deps
@@ -1 +1 @@
-Subproject commit 911e009961edb6964c8e63db5093d65afd2a002a
+Subproject commit d3db3d114ff7fb376fd9d02782069bb09846df24
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src
index a23d066..92e8905 160000
--- a/third_party/vulkan-validation-layers/src
+++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@
-Subproject commit a23d066d0e0b4219681be2a248478632d78f26f6
+Subproject commit 92e89050c4d26acbb88682ad912b34a7ae67d5c5
diff --git a/third_party/webgl/src b/third_party/webgl/src
index c01b768..8fc2a0d 160000
--- a/third_party/webgl/src
+++ b/third_party/webgl/src
@@ -1 +1 @@
-Subproject commit c01b768bce4a143e152c1870b6ba99ea6267d2b0
+Subproject commit 8fc2a0dff53abfc0cf2c140d8420759b2036cc54
diff --git a/third_party/webgpu-cts/src b/third_party/webgpu-cts/src
index b043a4e..21ecca5 160000
--- a/third_party/webgpu-cts/src
+++ b/third_party/webgpu-cts/src
@@ -1 +1 @@
-Subproject commit b043a4eaef1e6c46e9c79abc381785aadd9ff057
+Subproject commit 21ecca5d71d440d8283069df3fd51263f68c38d7
diff --git a/third_party/xnnpack/BUILD.gn b/third_party/xnnpack/BUILD.gn
index 6a445bd..37658fc 100644
--- a/third_party/xnnpack/BUILD.gn
+++ b/third_party/xnnpack/BUILD.gn
@@ -353,6 +353,7 @@
       ":qs8-packw_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl-avx512vnni",
       ":qs8-packw_x64",
       ":qs8-qc2w-gemm_f16c-fma-avx2",
+      ":qs8-qc2w-gemm_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl",
       ":qs8-qc2w-gemm_x64",
       ":qs8-qc4w-gemm_avx-no-avx2-no-f16c-no-fma",
       ":qs8-qc4w-gemm_avx2-avxvnni-f16c-fma-gfni",
@@ -878,6 +879,7 @@
       ":qs8-packw_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl-avx512vnni_standalone",
       ":qs8-packw_x64_standalone",
       ":qs8-qc2w-gemm_f16c-fma-avx2_standalone",
+      ":qs8-qc2w-gemm_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl_standalone",
       ":qs8-qc2w-gemm_x64_standalone",
       ":qs8-qc4w-gemm_avx-no-avx2-no-f16c-no-fma_standalone",
       ":qs8-qc4w-gemm_avx2-avxvnni-f16c-fma-gfni_standalone",
@@ -1098,7 +1100,7 @@
       ":xx-transposev_x64_standalone",
     ]
   }
-} else if (current_cpu == "arm64" || current_cpu == "arm64e") {
+} else if (current_cpu == "arm64") {
   if (build_with_chromium) {
     xnnpack_deps = [
       ":configs_arm64",
@@ -21443,7 +21445,7 @@
       sources = [
         "src/include/xnnpack.h",
         "src/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-1x8c8-minmax-avx2-madd.c",
-        "src/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-8x8c8-minmax-avx2-madd.c",
+        "src/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-5x8c8-minmax-avx2-madd.c",
       ]
 
       configs -= [ "//build/config/compiler:chromium_code" ]
@@ -21474,7 +21476,82 @@
       sources = [
         "src/include/xnnpack.h",
         "src/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-1x8c8-minmax-avx2-madd.c",
-        "src/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-8x8c8-minmax-avx2-madd.c",
+        "src/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-5x8c8-minmax-avx2-madd.c",
+      ]
+
+      configs -= [ "//build/config/compiler:chromium_code" ]
+      configs += [ "//build/config/compiler:no_chromium_code" ]
+      configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ]
+      configs += [ ":xnnpack_private_config" ]
+
+      deps = [
+        "//third_party/cpuinfo",
+        "//third_party/fp16",
+        "//third_party/fxdiv",
+        "//third_party/pthreadpool:pthreadpool_standalone",
+      ]
+
+      public_configs = [ ":xnnpack_public_config" ]
+
+      if (!(is_android && use_order_profiling)) {
+        assert_no_deps = [ "//base" ]
+      }
+    }
+  }
+
+  if (build_with_chromium) {
+    source_set(
+        "qs8-qc2w-gemm_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl") {
+      cflags = [
+        "-mavx512bw",
+        "-mavx512cd",
+        "-mavx512dq",
+        "-mavx512f",
+        "-mavx512vl",
+        "-mf16c",
+        "-mfma",
+      ]
+
+      sources = [
+        "src/include/xnnpack.h",
+        "src/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-1x8c8-minmax-avx256skx-madd.c",
+        "src/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-5x8c8-minmax-avx256skx-madd.c",
+      ]
+
+      configs -= [ "//build/config/compiler:chromium_code" ]
+      configs += [ "//build/config/compiler:no_chromium_code" ]
+      configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ]
+      configs += [ ":xnnpack_private_config" ]
+
+      deps = [
+        "//third_party/cpuinfo",
+        "//third_party/fp16",
+        "//third_party/fxdiv",
+        "//third_party/pthreadpool",
+      ]
+
+      public_configs = [ ":xnnpack_public_config" ]
+    }
+  }
+
+  # This is a target that cannot depend on //base.
+  if (build_with_internal_optimization_guide) {
+    source_set(
+        "qs8-qc2w-gemm_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl_standalone") {
+      cflags = [
+        "-mavx512bw",
+        "-mavx512cd",
+        "-mavx512dq",
+        "-mavx512f",
+        "-mavx512vl",
+        "-mf16c",
+        "-mfma",
+      ]
+
+      sources = [
+        "src/include/xnnpack.h",
+        "src/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-1x8c8-minmax-avx256skx-madd.c",
+        "src/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-5x8c8-minmax-avx256skx-madd.c",
       ]
 
       configs -= [ "//build/config/compiler:chromium_code" ]
@@ -35239,7 +35316,7 @@
   }
 }
 
-if (current_cpu == "arm64" || current_cpu == "arm64e") {
+if (current_cpu == "arm64") {
   if (build_with_chromium) {
     source_set("configs_arm64") {
       cflags = []
@@ -36513,7 +36590,7 @@
 
       sources = [
         "src/include/xnnpack.h",
-        "src/src/f16-raddstoreexpminusmax/gen/f16-raddstoreexpminusmax-neonfp16arith-rr2-p2-u32.c",
+        "src/src/f16-raddstoreexpminusmax/gen/f16-raddstoreexpminusmax-neonfp16arith-rr2-p2-u32-acc2.c",
       ]
 
       configs -= [ "//build/config/compiler:chromium_code" ]
@@ -36539,7 +36616,7 @@
 
       sources = [
         "src/include/xnnpack.h",
-        "src/src/f16-raddstoreexpminusmax/gen/f16-raddstoreexpminusmax-neonfp16arith-rr2-p2-u32.c",
+        "src/src/f16-raddstoreexpminusmax/gen/f16-raddstoreexpminusmax-neonfp16arith-rr2-p2-u32-acc2.c",
       ]
 
       configs -= [ "//build/config/compiler:chromium_code" ]
diff --git a/third_party/xnnpack/README.chromium b/third_party/xnnpack/README.chromium
index eab72c35..b9af641 100644
--- a/third_party/xnnpack/README.chromium
+++ b/third_party/xnnpack/README.chromium
@@ -2,7 +2,7 @@
 Short Name: xnnpack
 URL: https://github.com/google/xnnpack
 Version: N/A
-Revision: e8aad3cc4ffb7259c4aab6dfb922bfbef0ef8be0
+Revision: 066e3e72b05e56441aebaa57c57fad9280d869c8
 Update Mechanism: Manual
 License: BSD-3-Clause
 License File: src/LICENSE
diff --git a/third_party/xnnpack/build_identifier.c b/third_party/xnnpack/build_identifier.c
index 4e89f6c..2469317 100644
--- a/third_party/xnnpack/build_identifier.c
+++ b/third_party/xnnpack/build_identifier.c
@@ -673,9 +673,11 @@
 // - external/xnnpack+/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-1x2-minmax-fp32-scalar-fmagic.c
 // - external/xnnpack+/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-1x4-minmax-fp32-scalar-fmagic.c
 // - external/xnnpack+/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-1x8c8-minmax-avx2-madd.c
+// - external/xnnpack+/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-1x8c8-minmax-avx256skx-madd.c
 // - external/xnnpack+/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-3x4-minmax-fp32-scalar-fmagic.c
 // - external/xnnpack+/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-4x4-minmax-fp32-scalar-fmagic.c
-// - external/xnnpack+/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-8x8c8-minmax-avx2-madd.c
+// - external/xnnpack+/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-5x8c8-minmax-avx2-madd.c
+// - external/xnnpack+/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-5x8c8-minmax-avx256skx-madd.c
 // - external/xnnpack+/src/qs8-qc4w-gemm/gen/qs8-qc4w-gemm-1x16c8-minmax-fp32-asm-amd64-avx512vnni.S
 // - external/xnnpack+/src/qs8-qc4w-gemm/gen/qs8-qc4w-gemm-1x16c8-minmax-fp32-avx512skx-madd-prfm.c
 // - external/xnnpack+/src/qs8-qc4w-gemm/gen/qs8-qc4w-gemm-1x16c8-minmax-fp32-avx512vnnigfni-prfm.c
@@ -1015,10 +1017,10 @@
 #include <string.h>
 
 static const uint8_t xnn_build_identifier[] = {
-  212,  52, 170,   2,  96, 133, 189,  45,
-  137,  90, 158, 146,  20,  18,  57, 119,
-  138, 206,   0, 112,  97, 247, 156, 118,
-  237,   9,  45,  71, 170,  23,  53, 172
+  215,  10, 102, 239, 210, 155,  46, 182,
+  149,   3,  90, 253, 180, 133, 183, 239,
+   35, 182, 159,  29, 205, 227, 122, 190,
+   57,  97, 150, 106, 176, 120,  27,  86
 };
 
 size_t xnn_experimental_get_build_identifier_size() {
diff --git a/third_party/xnnpack/src b/third_party/xnnpack/src
index e8aad3c..066e3e7 160000
--- a/third_party/xnnpack/src
+++ b/third_party/xnnpack/src
@@ -1 +1 @@
-Subproject commit e8aad3cc4ffb7259c4aab6dfb922bfbef0ef8be0
+Subproject commit 066e3e72b05e56441aebaa57c57fad9280d869c8
diff --git a/tools/android/avd/proto/android_35_google_apis_x64.textpb b/tools/android/avd/proto/android_35_google_apis_x64.textpb
index 51ca1d3..96e44ee 100644
--- a/tools/android/avd/proto/android_35_google_apis_x64.textpb
+++ b/tools/android/avd/proto/android_35_google_apis_x64.textpb
@@ -5,8 +5,8 @@
 # Configuration for an Android 15 (V, API 35) AVD on google_apis on x86_64
 
 emulator_package {
-  package_name: "chromium/third_party/android_sdk/public/emulator"
-  version: "v8yrLOpMlE0if7NxVuSlX0Etnq0k_FLX_hmYksbVSm0C"  # 36.1.9 (Stable)
+  package_name: "chromium/third_party/android_sdk/public/emulator/linux-amd64"
+  version: "QgDCxG9OzoQx04LpwnENgTz3gby5-Kyx6Rsv5yl91p4C"  # 36.4.9 (Stable)
 }
 
 system_image_package {
@@ -17,9 +17,9 @@
 
 avd_package {
   package_name: "chromium/third_party/android_sdk/public/avds/android-35/google_apis/x86_64"
-  # Created in https://ci.chromium.org/ui/b/8705163385740243089
+  # Created in https://ci.chromium.org/ui/b/8689047532256932641
   # Patched gmscore version 25.07.33 in https://crrev.com/c/6377466
-  version: "JPWw6vWrx3mM3U5Hn-Ug9xDlhsxQsNuBHRSlSraVP50C"
+  version: "TrrXyrH92BTO8ovfOpBCjR_xXmd0fJ_XQaYdLEyH6i4C"
 }
 avd_name: "android_35_google_apis_x64"
 
diff --git a/tools/android/avd/proto/android_35_google_apis_x64_local.textpb b/tools/android/avd/proto/android_35_google_apis_x64_local.textpb
index d24d5f6..448bfc9 100644
--- a/tools/android/avd/proto/android_35_google_apis_x64_local.textpb
+++ b/tools/android/avd/proto/android_35_google_apis_x64_local.textpb
@@ -5,8 +5,8 @@
 # Configuration for an Android 15 (V, API 35) AVD on google_apis on x86_64
 
 emulator_package {
-  package_name: "chromium/third_party/android_sdk/public/emulator"
-  version: "v8yrLOpMlE0if7NxVuSlX0Etnq0k_FLX_hmYksbVSm0C"  # 36.1.9 (Stable)
+  package_name: "chromium/third_party/android_sdk/public/emulator/linux-amd64"
+  version: "QgDCxG9OzoQx04LpwnENgTz3gby5-Kyx6Rsv5yl91p4C"  # 36.4.9 (Stable)
 }
 
 system_image_package {
@@ -17,9 +17,9 @@
 
 avd_package {
   package_name: "chromium/third_party/android_sdk/public/avds/android-35/google_apis/x86_64"
-  # Created in https://ci.chromium.org/ui/b/8705163385740243089
+  # Created in https://ci.chromium.org/ui/b/8689047532256932641
   # Patched gmscore version 25.07.33 in https://crrev.com/c/6377466
-  version: "Ba12jK9v3f5Wevl1lQy0dLC6cYEK0Gda0Y-Vz5sssgYC"
+  version: "s8fbeUiKap-1gH-OM0dEYagjmjszjstZo7ORNnV8QLsC"
 }
 avd_name: "android_35_google_apis_x64"
 
diff --git a/tools/android/avd/proto/android_35_google_apis_x64_tablet.textpb b/tools/android/avd/proto/android_35_google_apis_x64_tablet.textpb
index 07fc87b..8cafc001 100644
--- a/tools/android/avd/proto/android_35_google_apis_x64_tablet.textpb
+++ b/tools/android/avd/proto/android_35_google_apis_x64_tablet.textpb
@@ -6,8 +6,8 @@
 # with tablet form factor - 10.05", 1600x2560, xhdpi
 
 emulator_package {
-  package_name: "chromium/third_party/android_sdk/public/emulator"
-  version: "v8yrLOpMlE0if7NxVuSlX0Etnq0k_FLX_hmYksbVSm0C"  # 36.1.9 (Stable)
+  package_name: "chromium/third_party/android_sdk/public/emulator/linux-amd64"
+  version: "QgDCxG9OzoQx04LpwnENgTz3gby5-Kyx6Rsv5yl91p4C"  # 36.4.9 (Stable)
 }
 
 system_image_package {
@@ -18,9 +18,9 @@
 
 avd_package {
   package_name: "chromium/third_party/android_sdk/public/avds/android-35/google_apis/x86_64"
-  # Created in https://ci.chromium.org/ui/b/8705163385740243089
+  # Created in https://ci.chromium.org/ui/b/8689047532256932641
   # Patched gmscore version 25.07.33 in https://crrev.com/c/6377466
-  version: "_jeUe3ZQRSS5ozUrs3B28EzYeC2_nrn0DIPUU4AAl2MC"
+  version: "YVqwqHpSJC_T5-0U0X0w7KAaI-38-3nAb-WW7B0-PD4C"
 }
 avd_name: "android_35_google_apis_x64"
 
diff --git a/tools/android/avd/proto/android_35_google_apis_x64_tablet_landscape.textpb b/tools/android/avd/proto/android_35_google_apis_x64_tablet_landscape.textpb
index 568450a..19adef5 100644
--- a/tools/android/avd/proto/android_35_google_apis_x64_tablet_landscape.textpb
+++ b/tools/android/avd/proto/android_35_google_apis_x64_tablet_landscape.textpb
@@ -6,8 +6,8 @@
 # with tablet form factor - 10.05", 2560x1600, xhdpi
 
 emulator_package {
-  package_name: "chromium/third_party/android_sdk/public/emulator"
-  version: "v8yrLOpMlE0if7NxVuSlX0Etnq0k_FLX_hmYksbVSm0C"  # 36.1.9 (Stable)
+  package_name: "chromium/third_party/android_sdk/public/emulator/linux-amd64"
+  version: "QgDCxG9OzoQx04LpwnENgTz3gby5-Kyx6Rsv5yl91p4C"  # 36.4.9 (Stable)
 }
 
 system_image_package {
@@ -18,9 +18,9 @@
 
 avd_package {
   package_name: "chromium/third_party/android_sdk/public/avds/android-35/google_apis/x86_64"
-  # Created in https://ci.chromium.org/ui/b/8705163385740243089
+  # Created in https://ci.chromium.org/ui/b/8689047532256932641
   # Patched gmscore version 25.07.33 in https://crrev.com/c/6377466
-  version: "MDO-tQeLGYG29nk2FMNk5phWrZc_isQ5IxuhRNsQYuMC"
+  version: "v630aBillM_qXVkEd9dW-6iyHSkc_qfhusWHFyTXHkwC"
 }
 avd_name: "android_35_google_apis_x64"
 
diff --git a/tools/android/avd/proto/android_35_google_apis_x64_tablet_landscape_local.textpb b/tools/android/avd/proto/android_35_google_apis_x64_tablet_landscape_local.textpb
index 33c5d3e3..1f5563a7 100644
--- a/tools/android/avd/proto/android_35_google_apis_x64_tablet_landscape_local.textpb
+++ b/tools/android/avd/proto/android_35_google_apis_x64_tablet_landscape_local.textpb
@@ -6,8 +6,8 @@
 # with tablet form factor - 10.05", 2560x1600, xhdpi
 
 emulator_package {
-  package_name: "chromium/third_party/android_sdk/public/emulator"
-  version: "v8yrLOpMlE0if7NxVuSlX0Etnq0k_FLX_hmYksbVSm0C"  # 36.1.9 (Stable)
+  package_name: "chromium/third_party/android_sdk/public/emulator/linux-amd64"
+  version: "QgDCxG9OzoQx04LpwnENgTz3gby5-Kyx6Rsv5yl91p4C"  # 36.4.9 (Stable)
 }
 
 system_image_package {
@@ -18,9 +18,9 @@
 
 avd_package {
   package_name: "chromium/third_party/android_sdk/public/avds/android-35/google_apis/x86_64"
-  # Created in https://ci.chromium.org/ui/b/8705163385740243089
+  # Created in https://ci.chromium.org/ui/b/8689047532256932641
   # Patched gmscore version 25.07.33 in https://crrev.com/c/6377466
-  version: "FV7x04xy9IciguKchoAImXLAqKExaolYtWUnZePh6L0C"
+  version: "8SfG1ovsDNTmt3izPqaEOb0xnS0c_UEEzMtBYTxjv38C"
 }
 avd_name: "android_35_google_apis_x64"
 
diff --git a/tools/android/avd/proto/android_35_google_apis_x64_tablet_local.textpb b/tools/android/avd/proto/android_35_google_apis_x64_tablet_local.textpb
index b7e7607..c5e2e711 100644
--- a/tools/android/avd/proto/android_35_google_apis_x64_tablet_local.textpb
+++ b/tools/android/avd/proto/android_35_google_apis_x64_tablet_local.textpb
@@ -6,8 +6,8 @@
 # with tablet form factor - 10.05", 1600x2560, xhdpi
 
 emulator_package {
-  package_name: "chromium/third_party/android_sdk/public/emulator"
-  version: "v8yrLOpMlE0if7NxVuSlX0Etnq0k_FLX_hmYksbVSm0C"  # 36.1.9 (Stable)
+  package_name: "chromium/third_party/android_sdk/public/emulator/linux-amd64"
+  version: "QgDCxG9OzoQx04LpwnENgTz3gby5-Kyx6Rsv5yl91p4C"  # 36.4.9 (Stable)
 }
 
 system_image_package {
@@ -18,9 +18,9 @@
 
 avd_package {
   package_name: "chromium/third_party/android_sdk/public/avds/android-35/google_apis/x86_64"
-  # Created in https://ci.chromium.org/ui/b/8705163385740243089
+  # Created in https://ci.chromium.org/ui/b/8689047532256932641
   # Patched gmscore version 25.07.33 in https://crrev.com/c/6377466
-  version: "p0lZavdtJZt3r0ibnAeg05J_llP6S6nt1kyDdGaGwlIC"
+  version: "6ORqFLr2IwwWA7LKBXKvBnVN9vBzl4pJSIb-TfROsTsC"
 }
 avd_name: "android_35_google_apis_x64"
 
diff --git a/tools/autotest/.vpython3 b/tools/autotest/.vpython3
index 6b21127..71da218 100644
--- a/tools/autotest/.vpython3
+++ b/tools/autotest/.vpython3
@@ -1,6 +1,11 @@
 python_version: "3.11"
 
 wheel: <
+  name: "infra/python/wheels/click-py2_py3"
+  version: "version:7.0"
+>
+
+wheel: <
   name: "infra/python/wheels/colorama-py2_py3"
   version: "version:0.4.1"
 >
@@ -29,6 +34,7 @@
   name: "infra/python/wheels/rich-py3"
   version: "version:13.2.0"
 >
+
 wheel: <
   name: "infra/python/wheels/typing-extensions-py3"
   version: "version:4.0.1"
diff --git a/tools/autotest/autotest_test.py b/tools/autotest/autotest_test.py
index 3499591..31ac96e 100755
--- a/tools/autotest/autotest_test.py
+++ b/tools/autotest/autotest_test.py
@@ -263,10 +263,6 @@
     self.mock_cache.Find.return_value = None
     self.mock_cache.GetBuildNinjaMtime.return_value = 100
 
-    self.args = argparse.Namespace(run_all=False,
-                                   run_changed=False,
-                                   target_index=None)
-
   def test_mixed_targets(self):
     # Simulate `gn refs` output for the command:
     # $ gn refs out_/Default --all --relation=source --relation=input \
@@ -281,9 +277,9 @@
 //third_party/blink/renderer/platform/wtf:wtf_unittests
 //third_party/blink/renderer/platform/wtf:wtf_unittests_sources
 """
-    self.args.run_all = True
-    targets, _ = target_finder.FindTestTargets(self.mock_cache, self.out_dir,
-                                               ['foo.cc'], self.args)
+    targets, _ = target_finder.FindTestTargets(self.mock_cache,
+                                               self.out_dir, ['foo.cc'],
+                                               run_all=True)
 
     self.assertIn('chrome/test:browser_tests', targets)
     self.assertIn('third_party/blink/renderer/platform/wtf:wtf_unittests',
@@ -296,7 +292,7 @@
 //chrome/android:chrome_public_test_apk__test_apk
 """
     targets, _ = target_finder.FindTestTargets(self.mock_cache, self.out_dir,
-                                               ['foo.java'], self.args)
+                                               ['foo.java'])
     # Should strip suffix
     self.assertIn('chrome/android:chrome_public_test_apk', targets)
 
@@ -305,7 +301,7 @@
 //chrome/test:browser_tests
 """
     targets, _ = target_finder.FindTestTargets(self.mock_cache, self.out_dir,
-                                               ['foo.cc'], self.args)
+                                               ['foo.cc'])
     self.assertIn('chrome/test:browser_tests', targets)
 
   def test_target_ambiguity_prompt(self):
@@ -316,7 +312,7 @@
     with mock.patch('utils.command_util.HaveUserPickTarget',
                     return_value='//chrome/test:unit_tests') as mock_pick:
       targets, _ = target_finder.FindTestTargets(self.mock_cache, self.out_dir,
-                                                 ['foo.cc'], self.args)
+                                                 ['foo.cc'])
       self.assertEqual(['chrome/test:unit_tests'], targets)
       mock_pick.assert_called_once()
 
@@ -326,9 +322,9 @@
 //chrome/test:browser_tests
 """
     # Sorted: browser_tests, unit_tests. Index 0 -> browser_tests
-    self.args.target_index = 0
-    targets, _ = target_finder.FindTestTargets(self.mock_cache, self.out_dir,
-                                               ['foo.cc'], self.args)
+    targets, _ = target_finder.FindTestTargets(self.mock_cache,
+                                               self.out_dir, ['foo.cc'],
+                                               target_index=0)
     self.assertEqual(['chrome/test:browser_tests'], targets)
 
   def test_run_all(self):
@@ -336,9 +332,9 @@
 //chrome/test:unit_tests
 //chrome/test:browser_tests
 """
-    self.args.run_all = True
-    targets, _ = target_finder.FindTestTargets(self.mock_cache, self.out_dir,
-                                               ['foo.cc'], self.args)
+    targets, _ = target_finder.FindTestTargets(self.mock_cache,
+                                               self.out_dir, ['foo.cc'],
+                                               run_all=True)
     self.assertEqual(len(targets), 2)
     self.assertIn('chrome/test:browser_tests', targets)
     self.assertIn('chrome/test:unit_tests', targets)
diff --git a/tools/autotest/finders/target_finder.py b/tools/autotest/finders/target_finder.py
index 3aa37b9..26e245d1 100644
--- a/tools/autotest/finders/target_finder.py
+++ b/tools/autotest/finders/target_finder.py
@@ -78,10 +78,13 @@
   return targets
 
 
-def FindTestTargets(target_cache: TargetCache, out_dir: str, paths: list[str],
-                    args: argparse.Namespace) -> tuple[list[str], bool]:
-  run_all: bool = args.run_all or args.run_changed
-  target_index: int | None = args.target_index
+def FindTestTargets(target_cache: TargetCache,
+                    out_dir: str,
+                    paths: list[str],
+                    run_all: bool = False,
+                    run_changed: bool = False,
+                    target_index: int | None = None) -> tuple[list[str], bool]:
+  run_all: bool = run_all or run_changed
 
   # Normalize paths, so they can be cached.
   paths = [os.path.realpath(p) for p in paths]
@@ -138,4 +141,4 @@
   # Remove the // prefix to turn GN label into ninja target.
   test_targets_gn: list[str] = [t[2:] for t in test_targets]
 
-  return (test_targets_gn, used_cache)
\ No newline at end of file
+  return (test_targets_gn, used_cache)
diff --git a/tools/autotest/main.py b/tools/autotest/main.py
index 5dd912a6..54cf1c35 100644
--- a/tools/autotest/main.py
+++ b/tools/autotest/main.py
@@ -30,10 +30,10 @@
 autotest.py -C out/foo StringUtilTest.IsStringUTF8 SpanTest.AsStringView
 """
 
-import argparse
 import os
 import sys
 import shutil
+import click
 
 import filters
 import finders.file_finder as file_finder
@@ -42,176 +42,107 @@
 import utils.command_util as command
 import utils.constants as const
 import utils.telemetry as telemetry
+
 from utils.command_error import AutotestError, CommandError
+from utils.options import AutotestConfig, Formatter, autotest_options
 
 sys.path.append(str(const.SRC_DIR / 'build' / 'android'))
 from pylib import constants
 
 
+@click.command(cls=Formatter,
+               help=__doc__,
+               context_settings=dict(ignore_unknown_options=True,
+                                     allow_interspersed_args=False,
+                                     help_option_names=['-h', '--help']))
+@autotest_options
+@click.argument('files', nargs=-1)
+@click.pass_context
 @telemetry.tracer.start_as_current_span('chromium.tools.autotest.main')
-def main() -> int:
-  parser: argparse.ArgumentParser = argparse.ArgumentParser(
-      prog='tools/autotest.py',
-      description=__doc__,
-      formatter_class=argparse.RawTextHelpFormatter)
-  parser.add_argument('--out-dir',
-                      '--out_dir',
-                      '--output-directory',
-                      '--output_directory',
-                      '-C',
-                      metavar='OUT_DIR',
-                      help='output directory of the build')
-  parser.add_argument('--remote-search',
-                      '--remote_search',
-                      '-r',
-                      action='store_true',
-                      help='Search for tests using a remote service')
-  parser.add_argument('--name',
-                      action='append',
-                      help='Search for the test by name, and apply test filter')
-  parser.add_argument(
-      '--run-all',
-      '--run_all',
-      action='store_true',
-      help='Run all tests for the file or directory, instead of just one')
-  parser.add_argument(
-      '--target-index',
-      '--target_index',
-      type=int,
-      help='When the target is ambiguous, choose the one with this index.')
-  parser.add_argument(
-      '--path-index',
-      '--path_index',
-      type=int,
-      help='When the test path is ambiguous, choose the one with this index.')
-  parser.add_argument(
-      '--run-changed',
-      '--run_changed',
-      action='store_true',
-      help='Run tests files modified since this branch diverged from main.')
-  parser.add_argument('--line',
-                      type=int,
-                      help='run only the test on this line number. c++ only.')
-  parser.add_argument('--gtest-filter',
-                      '--gtest_filter',
-                      '-f',
-                      metavar='FILTER',
-                      help='test filter')
-  parser.add_argument('--test-policy-to-pref-mappings-filter',
-                      '--test_policy_to_pref_mappings_filter',
-                      metavar='FILTER',
-                      help='policy pref mappings test filter')
-  parser.add_argument(
-      '--dry-run',
-      '--dry_run',
-      '-n',
-      action='store_true',
-      help='Print ninja and test run commands without executing them.')
-  parser.add_argument(
-      '--quiet',
-      '-q',
-      action='store_true',
-      help='Do not print while building, only print if build fails.')
-  parser.add_argument(
-      '--no-try-android-wrappers',
-      '--no_try_android_wrappers',
-      action='store_true',
-      help='Do not try to use Android test wrappers to run tests.')
-  parser.add_argument('--no-fast-local-dev',
-                      '--no_fast_local_dev',
-                      action='store_true',
-                      help='Do not add --fast-local-dev for Android tests.')
-  parser.add_argument('--no-single-variant',
-                      '--no_single_variant',
-                      action='store_true',
-                      help='Do not add --single-variant for Android tests.')
-  parser.add_argument('--no-build',
-                      '--no-build',
-                      action='store_true',
-                      help='Do not build before running tests.')
-  parser.add_argument('files',
-                      metavar='FILE_NAME',
-                      nargs='*',
-                      help='test suite file (eg. FooTest.java) or test name')
+def main(ctx, **kwargs) -> int:
+  # Capture "extras" (arguments click didn't recognize)
+  kwargs['extras'] = ctx.args
 
-  args, _extras = parser.parse_known_args()
+  config: AutotestConfig = AutotestConfig(**kwargs)
 
-  if args.out_dir:
-    constants.SetOutputDirectory(args.out_dir)
+  if config.out_dir:
+    constants.SetOutputDirectory(config.out_dir)
   constants.CheckOutputDirectory()
-  out_dir: str = constants.GetOutDirectory()
+  out_dir = constants.GetOutDirectory()
 
   if not os.path.isdir(out_dir):
-    parser.error(f'OUT_DIR "{out_dir}" does not exist.')
+    raise click.UsageError(f'OUT_DIR "{out_dir}" does not exist.')
+
   target_cache: target_finder.TargetCache = target_finder.TargetCache(out_dir)
 
-  if not args.run_changed and not args.files and not args.name:
-    parser.error('Specify a file to test or use --run-changed')
+  if not config.run_changed and not config.files and not config.name:
+    raise click.UsageError('Specify a file to test or use --run-changed')
 
   # Cog is almost unusable with local search, so turn on remote_search.
-  use_remote_search: bool = args.remote_search
+  use_remote_search: bool = config.remote_search
   if not use_remote_search and const.SRC_DIR.parts[:3] == ('/', 'google',
                                                            'cog'):
     if const.DEBUG:
-      print('Detected cog, turning on remote-search.')
+      click.echo('Detected cog, turning on remote-search.')
     use_remote_search = True
 
-  gtest_filter: str | None = args.gtest_filter
-
   # Don't try to search if rg is not installed, and use the old behavior.
   if not use_remote_search and not shutil.which('rg'):
-    if not args.quiet:
-      print(
+    if not config.quiet:
+      click.echo(
           'rg command not found. Install ripgrep to enable running tests by name.'
       )
-    files_to_test = args.files
+    files_to_test = list(config.files)
     test_names = []
   else:
-    test_names = [f for f in args.files if not file_finder.IsProbablyFile(f)]
-    files_to_test = [f for f in args.files if file_finder.IsProbablyFile(f)]
+    test_names = [f for f in config.files if not file_finder.IsProbablyFile(f)]
+    files_to_test = [f for f in config.files if file_finder.IsProbablyFile(f)]
 
-  if args.name:
-    test_names.extend(args.name)
+  if config.name:
+    test_names.extend(config.name)
+
+  current_gtest_filter: str | None = config.gtest_filter
   if test_names:
-    files, filter = file_finder.SearchForTestsByName(test_names, args.quiet,
-                                                     use_remote_search)
-    if not gtest_filter:
-      gtest_filter = filter
-    files_to_test.extend(files)
+    found_files, found_filter = file_finder.SearchForTestsByName(
+        test_names, config.quiet, use_remote_search)
+    if not current_gtest_filter:
+      current_gtest_filter = found_filter
+    files_to_test.extend(found_files)
 
-  if args.run_changed:
+  if config.run_changed:
     files_to_test.extend(file_finder.GetChangedTestFiles())
-    # Remove duplicates.
     files_to_test = list(set(files_to_test))
 
   filenames: list[str] = []
-  for file in files_to_test:
+  for f in files_to_test:
     filenames.extend(
-        file_finder.FindMatchingTestFiles(file, use_remote_search,
-                                          args.path_index))
+        file_finder.FindMatchingTestFiles(f, use_remote_search,
+                                          config.path_index))
 
   if not filenames:
     command.ExitWithMessage('No associated test files found.')
 
   targets, used_cache = target_finder.FindTestTargets(target_cache, out_dir,
-                                                      filenames, args)
+                                                      filenames, config.run_all,
+                                                      config.run_changed,
+                                                      config.target_index)
 
-  if not gtest_filter:
-    gtest_filter = filters.BuildTestFilter(filenames, args.line)
+  if not current_gtest_filter:
+    current_gtest_filter = filters.BuildTestFilter(filenames, config.line)
 
-  if not gtest_filter:
+  if not current_gtest_filter:
     command.ExitWithMessage('Failed to derive a gtest filter')
 
-  pref_mapping_filter: str | None = args.test_policy_to_pref_mappings_filter
+  pref_mapping_filter: str | None = config.test_policy_to_pref_mappings_filter
   if not pref_mapping_filter:
     pref_mapping_filter = filters.BuildPrefMappingTestFilter(filenames)
 
   assert targets
 
-  if not args.no_build:
+  if not config.no_build:
     build_ok: bool = test_executor.BuildTestTargets(out_dir, targets,
-                                                    args.dry_run, args.quiet,
-                                                    False)
+                                                    config.dry_run,
+                                                    config.quiet, False)
 
     # If we used the target cache, it's possible we chose the wrong target
     # because a gn file was changed. The build step above will check for gn
@@ -220,32 +151,34 @@
     if used_cache and not target_cache.IsStillValid():
       target_cache = target_finder.TargetCache(out_dir)
       new_targets, _ = target_finder.FindTestTargets(target_cache, out_dir,
-                                                     filenames, args)
+                                                     filenames, config.run_all,
+                                                     config.run_changed,
+                                                     config.target_index)
       if targets != new_targets:
         # Note that this can happen, for example, if you rename a test target.
-        print('gn config was changed, trying to build again', file=sys.stderr)
+        click.echo('gn config was changed, trying to build again', err=True)
         targets = new_targets
-        build_ok: bool = test_executor.BuildTestTargets(out_dir, targets,
-                                                        args.dry_run,
-                                                        args.quiet, True)
-    telemetry.RecordMainAttributes(targets, gtest_filter, used_cache, out_dir)
+        build_ok = test_executor.BuildTestTargets(out_dir, targets,
+                                                  config.dry_run, config.quiet,
+                                                  True)
+    telemetry.RecordMainAttributes(targets, current_gtest_filter, used_cache,
+                                   out_dir)
 
     if not build_ok:
       return 1
 
-  return test_executor.RunTestTargets(out_dir, targets, gtest_filter,
-                                      pref_mapping_filter, _extras,
-                                      args.dry_run,
-                                      args.no_try_android_wrappers,
-                                      args.no_fast_local_dev,
-                                      args.no_single_variant)
-
+  return test_executor.RunTestTargets(out_dir, targets, current_gtest_filter,
+                                      pref_mapping_filter, config.extras,
+                                      config.dry_run,
+                                      config.no_try_android_wrappers,
+                                      config.no_fast_local_dev,
+                                      config.no_single_variant)
 
 if __name__ == '__main__':
   telemetry.telemetry.initialize('chromium.tools.autotest')
 
   try:
-    sys.exit(main())
+    sys.exit(main(prog_name='tools/autotest.py'))
   except (AutotestError, CommandError) as e:
     print(e, file=sys.stderr)
     sys.exit(1)
diff --git a/tools/autotest/utils/options.py b/tools/autotest/utils/options.py
new file mode 100644
index 0000000..a3cc3ed
--- /dev/null
+++ b/tools/autotest/utils/options.py
@@ -0,0 +1,170 @@
+# Copyright 2026 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import click
+
+from dataclasses import dataclass, fields
+
+
+@dataclass
+class AutotestConfig:
+  out_dir: str | None
+  remote_search: bool | None
+  name: list[str] | None
+  run_all: bool | None
+  target_index: str | None
+  path_index: str | None
+  run_changed: bool | None
+  line: int | None
+  gtest_filter: str | None
+  test_policy_to_pref_mappings_filter: str | None
+  dry_run: bool | None
+  quiet: bool | None
+  no_try_android_wrappers: bool | None
+  no_fast_local_dev: bool | None
+  no_single_variant: bool | None
+  no_build: bool | None
+  files: tuple[str, ...]
+  extras: list[str] | None = None  # To hold ctx.args
+
+
+class Formatter(click.Command):
+
+  def format_help(self, ctx: click.Context, formatter: click.HelpFormatter):
+    """Overriding format_help to ensure the description is raw/unwrapped."""
+    self.format_usage(ctx, formatter)
+
+    if self.help:
+      formatter.write(f"\n{self.help}\n")
+
+    self.format_options(ctx, formatter)
+    self.format_epilog(ctx, formatter)
+
+  def format_usage(self, ctx: click.Context, formatter: click.HelpFormatter):
+
+    prog_name: str = ctx.command_path
+
+    pieces: list[str] = []
+    for param in self.get_params(ctx):
+      if isinstance(param, click.Option):
+
+        opts: list[str] = param.opts + param.secondary_opts
+
+        main_opt: str = max(opts, key=len) if opts else ""
+
+        if param.is_flag:
+          pieces.append(f"[{main_opt}]")
+        else:
+          metavar = param.metavar or param.name.upper()
+          pieces.append(f"[{main_opt} {metavar}]")
+
+    pieces.append("[FILE_NAME ...]")
+
+    formatter.write_usage(prog_name,
+                          " ".join(pieces),
+                          prefix='Usage: vpython3 ')
+
+  def format_options(self, ctx: click.Context, formatter: click.HelpFormatter):
+
+    with formatter.section('Positional arguments'):
+      formatter.write_dl([('FILE_NAME',
+                           'test suite file (eg. FooTest.java) or test name')])
+
+    opts: list[tuple[str, str]] = []
+    for param in self.get_params(ctx):
+
+      if isinstance(param, click.Option):
+        record: tuple[str, str] = param.get_help_record(ctx)
+        if record:
+          opts.append(record)
+
+    with formatter.section('Options'):
+      formatter.write_dl(opts)
+
+
+def autotest_options(f):
+  """Decorator to group all autotest CLI options."""
+  options = [
+      click.option('--out-dir',
+                   '--out_dir',
+                   '--output-directory',
+                   '--output_directory',
+                   '-C',
+                   metavar='OUT_DIR',
+                   help='output directory of the build'),
+      click.option('--remote-search',
+                   '--remote_search',
+                   '-r',
+                   is_flag=True,
+                   help='Search for tests using a remote service'),
+      click.option('--name',
+                   multiple=True,
+                   help='Search for the test by name, and apply test filter'),
+      click.option(
+          '--run-all',
+          '--run_all',
+          is_flag=True,
+          help='Run all tests for the file or directory, instead of just one'),
+      click.option(
+          '--target-index',
+          '--target_index',
+          type=int,
+          help='When the target is ambiguous, choose the one with this index.'),
+      click.option(
+          '--path-index',
+          '--path_index',
+          type=int,
+          help='When the test path is ambiguous, choose the one with this index.'
+      ),
+      click.option(
+          '--run-changed',
+          '--run_changed',
+          is_flag=True,
+          help='Run tests files modified since this branch diverged from main.'
+      ),
+      click.option('--line',
+                   type=int,
+                   help='run only the test on this line number. c++ only.'),
+      click.option('--gtest-filter',
+                   '--gtest_filter',
+                   '-f',
+                   metavar='FILTER',
+                   help='test filter'),
+      click.option('--test-policy-to-pref-mappings-filter',
+                   '--test_policy_to_pref_mappings_filter',
+                   metavar='FILTER',
+                   help='policy pref mappings test filter'),
+      click.option(
+          '--dry-run',
+          '--dry_run',
+          '-n',
+          is_flag=True,
+          help='Print ninja and test run commands without executing them.'),
+      click.option(
+          '--quiet',
+          '-q',
+          is_flag=True,
+          help='Do not print while building, only print if build fails.'),
+      click.option(
+          '--no-try-android-wrappers',
+          '--no_try_android_wrappers',
+          is_flag=True,
+          help='Do not try to use Android test wrappers to run tests.'),
+      click.option('--no-fast-local-dev',
+                   '--no_fast_local_dev',
+                   is_flag=True,
+                   help='Do not add --fast-local-dev for Android tests.'),
+      click.option('--no-single-variant',
+                   '--no_single_variant',
+                   is_flag=True,
+                   help='Do not add --single-variant for Android tests.'),
+      click.option('--no-build',
+                   '--no_build',
+                   is_flag=True,
+                   help='Do not build before running tests.'),
+  ]
+  # Apply in reverse so the first item in the list appears first in --help
+  for option in reversed(options):
+    f = option(f)
+  return f
diff --git a/tools/bisect-builds.py b/tools/bisect-builds.py
index 8fc6a11..276dda20 100755
--- a/tools/bisect-builds.py
+++ b/tools/bisect-builds.py
@@ -1247,6 +1247,8 @@
 
 
 class AndroidBuildMixin:
+  _64bit_platforms = ('android-arm64', 'android-x64', 'android-arm64-high')
+  _pure_64bit_platforms = ('android-desktop-x64')
 
   def __init__(self, options):
     super().__init__(options)
@@ -1256,29 +1258,54 @@
     if not self.device:
       raise BisectException('Failed to initialize device.')
     self.binary_name = self._get_apk_filename()
+    if 'Trichrome' in self.binary_name:
+      self.library_binary_name = self._get_library_filename()
 
-  def _get_apk_mapping(self):
-    sdk = self.device.build_version_sdk
+  def _get_apk_mapping(self, prefer_64bit=True):
     if self.apk == 'webview':
       return WEBVIEW_APK_FILENAMES
+
+    sdk = self.device.build_version_sdk
+    if sdk >= version_codes.Q:
+      if self.platform in self._pure_64bit_platforms and prefer_64bit:
+        mapping = TRICHROME64_APK_FILENAMES
+      elif self.platform in self._64bit_platforms and prefer_64bit:
+        mapping = TRICHROME64_32_APK_FILENAMES
+      else:
+        mapping = TRICHROME_APK_FILENAMES
+      if self.apk in mapping:
+        return mapping
+      raise BisectException(f'SDK {sdk} requires Trichrome.')
+
     # Need these logic to bisect very old build. Release binaries are stored
     # forever and occasionally there are requests to bisect issues introduced
     # in very old versions.
-    elif sdk < version_codes.LOLLIPOP:
+    if sdk < version_codes.LOLLIPOP:
       return CHROME_APK_FILENAMES
-    elif sdk < version_codes.NOUGAT:
+    if sdk < version_codes.NOUGAT:
       return CHROME_MODERN_APK_FILENAMES
-    else:
-      return MONOCHROME_APK_FILENAMES
+    return MONOCHROME_APK_FILENAMES
 
-  def _get_apk_filename(self):
-    apk_mapping = self._get_apk_mapping()
+  def _get_apk_filename(self, prefer_64bit=True):
+    apk_mapping = self._get_apk_mapping(prefer_64bit)
     if self.apk not in apk_mapping:
       raise BisectException(
           'Bisecting on Android only supported for these apks: [%s].' %
           '|'.join(apk_mapping))
     return apk_mapping[self.apk]
 
+  def _get_library_filename(self, prefer_64bit=True):
+    apk_mapping = None
+    if self.platform in self._pure_64bit_platforms and prefer_64bit:
+      apk_mapping = TRICHROME64_LIBRARY_FILENAMES
+    elif self.platform in self._64bit_platforms and prefer_64bit:
+      apk_mapping = TRICHROME64_32_LIBRARY_FILENAMES
+    else:
+      apk_mapping = TRICHROME_LIBRARY_FILENAMES
+    if self.apk not in apk_mapping:
+      return None
+    return apk_mapping[self.apk]
+
   def _show_available_apks(self, tempdir):
     """glob and show available apks for the path."""
     available_apks = []
@@ -1310,6 +1337,23 @@
 
   def _install_revision(self, download, tempdir):
     UnzipFilenameToDir(download, tempdir)
+    if 'Trichrome' in self.binary_name:
+      trichrome_library_filename = self._get_library_filename()
+      trichrome_library_path = glob.glob(
+          f'{tempdir}/*/apks/{trichrome_library_filename}')
+      if len(trichrome_library_path) == 0:
+        self._show_available_apks(tempdir)
+        raise BisectException(
+            f'Can not find {trichrome_library_filename} from {tempdir}')
+      trichrome_filename = self._get_apk_filename()
+      trichrome_path = glob.glob(f'{tempdir}/*/apks/{trichrome_filename}')
+      if len(trichrome_path) == 0:
+        self._show_available_apks(tempdir)
+        raise BisectException(
+            f'Can not find {trichrome_filename} from {tempdir}')
+      InstallOnAndroid(self.device, trichrome_library_path[0])
+      InstallOnAndroid(self.device, trichrome_path[0])
+      return
     apk_path = glob.glob(self._get_extract_binary_glob(tempdir))
     if len(apk_path) == 0:
       if self.apk == 'webview':
@@ -1355,67 +1399,6 @@
     return '%s/*/apks/%s' % (tempdir, binary_name)
 
 
-class AndroidTrichromeMixin(AndroidBuildMixin):
-
-  def __init__(self, options):
-    # "High end" releases of Chrome on Android include only 64 bit libs, while
-    # others include both 32 & 64 bit support. All releases of android-desktop
-    # are considered "high end", while releases for android-mobile are a mix.
-    self._64bit_platforms = ('android-arm64', 'android-x64',
-                             'android-arm64-high')
-    self._pure_64bit_platforms = ('android-desktop-x64', )
-    super().__init__(options)
-    if self.device.build_version_sdk < version_codes.Q:
-      raise BisectException("Trichrome is only supported after Android Q.")
-    self.library_binary_name = self._get_library_filename()
-
-  def _get_apk_mapping(self, prefer_64bit=True):
-    if self.platform in self._pure_64bit_platforms and prefer_64bit:
-      return TRICHROME64_APK_FILENAMES
-    elif self.platform in self._64bit_platforms and prefer_64bit:
-      return TRICHROME64_32_APK_FILENAMES
-    else:
-      return TRICHROME_APK_FILENAMES
-
-  def _get_apk_filename(self, prefer_64bit=True):
-    apk_mapping = self._get_apk_mapping(prefer_64bit)
-    if self.apk not in apk_mapping:
-      raise BisectException(
-          'Bisecting on Android only supported for these apks: [%s].' %
-          '|'.join(apk_mapping))
-    return apk_mapping[self.apk]
-
-  def _get_library_filename(self, prefer_64bit=True):
-    apk_mapping = None
-    if self.platform in self._pure_64bit_platforms and prefer_64bit:
-      apk_mapping = TRICHROME64_LIBRARY_FILENAMES
-    elif self.platform in self._64bit_platforms and prefer_64bit:
-      apk_mapping = TRICHROME64_32_LIBRARY_FILENAMES
-    else:
-      apk_mapping = TRICHROME_LIBRARY_FILENAMES
-    if self.apk not in apk_mapping:
-      raise BisectException(
-          'Bisecting for Android Trichrome only supported for these apks: [%s].'
-          % '|'.join(apk_mapping))
-    return apk_mapping[self.apk]
-
-  def _install_revision(self, download, tempdir):
-    UnzipFilenameToDir(download, tempdir)
-    trichrome_library_filename = self._get_library_filename()
-    trichrome_library_path = glob.glob(
-        f'{tempdir}/*/apks/{trichrome_library_filename}')
-    if len(trichrome_library_path) == 0:
-      self._show_available_apks(tempdir)
-      raise BisectException(
-          f'Can not find {trichrome_library_filename} from {tempdir}')
-    trichrome_filename = self._get_apk_filename()
-    trichrome_path = glob.glob(f'{tempdir}/*/apks/{trichrome_filename}')
-    if len(trichrome_path) == 0:
-      self._show_available_apks(tempdir)
-      raise BisectException(f'Can not find {trichrome_filename} from {tempdir}')
-    InstallOnAndroid(self.device, trichrome_library_path[0])
-    InstallOnAndroid(self.device, trichrome_path[0])
-
 
 class AndroidReleaseBuild(AndroidBuildMixin, ReleaseBuild):
 
@@ -1423,12 +1406,14 @@
     super().__init__(options)
     self.signed = options.signed
     # We could download the apk directly from build bucket
-    self.archive_name = self.binary_name
+    self.base_url = self._get_release_bucket()
 
-  def _get_apk_filename(self):
+  def _get_apk_filename(self, prefer_64bit=True):
     if self.apk == 'webview':
-      return 'AndroidWebview.apk'
-    return super()._get_apk_filename()
+      sdk = self.device.build_version_sdk
+      if sdk < version_codes.Q:
+        return 'AndroidWebview.apk'
+    return super()._get_apk_filename(prefer_64bit)
 
   def _get_release_bucket(self):
     if self.signed:
@@ -1436,10 +1421,32 @@
     else:
       return ANDROID_RELEASE_BASE_URL
 
+  def _get_archive_path(self, build_number, archive_name=None):
+    if archive_name is None:
+      archive_name = self.binary_name
+    platform_dir = self.listing_platform_dir.rstrip('/')
+    return f'{self.base_url}/{build_number}/{platform_dir}/{archive_name}'
+
+  def get_download_url(self, revision):
+    if 'Trichrome' in self.binary_name:
+      if not isinstance(revision, ChromiumVersion):
+        rev_ver = ChromiumVersion(revision)
+      else:
+        rev_ver = revision
+      if rev_ver >= ChromiumVersion('112'):
+        trichrome = self.binary_name
+        trichrome_library = self.library_binary_name
+      else:
+        trichrome = self._get_apk_filename(prefer_64bit=False)
+        trichrome_library = self._get_library_filename(prefer_64bit=False)
+      return {
+          'trichrome': self._get_archive_path(revision, trichrome),
+          'trichrome_library': self._get_archive_path(revision,
+                                                      trichrome_library),
+      }
+    return self._get_archive_path(revision)
+
   def _get_rev_list(self, min_rev=None, max_rev=None):
-    # Android release builds store archives directly in a GCS bucket that
-    # contains a large number of objects. Listing the full revision list takes
-    # too much time, so we should disallow it and fail fast.
     if not min_rev or not max_rev:
       raise BisectException(
           "Could not found enough revisions for Android %s release channel." %
@@ -1448,56 +1455,19 @@
 
   def _install_revision(self, download, tempdir):
     # AndroidRelease build downloads the apks directly from GCS bucket.
-    InstallOnAndroid(self.device, download)
-
-
-class AndroidTrichromeReleaseBuild(AndroidTrichromeMixin, AndroidReleaseBuild):
-
-  def __init__(self, options):
-    super().__init__(options)
-    # Release build will download the binary directly from GCS bucket.
-    self.archive_name = self.binary_name
-    self.library_archive_name = self.library_binary_name
-
-  def _get_library_filename(self, prefer_64bit=True):
-    if self.apk == 'chrome' and self.platform == 'android-arm64-high':
-      raise BisectException('chrome debug build is not supported for %s' %
-                            self.platform)
-    return super()._get_library_filename(prefer_64bit)
-
-  def get_download_url(self, revision):
-    # M112 is when we started serving 6432 to 4GB+ devices. Before this it was
-    # only to 6GB+ devices.
-    if revision >= ChromiumVersion('112'):
-      trichrome = self.binary_name
-      trichrome_library = self.library_binary_name
+    if 'Trichrome' in self.binary_name:
+      if not isinstance(download, dict):
+        raise Exception("Trichrome should download multiple files from GCS.")
+      InstallOnAndroid(self.device, download['trichrome_library'])
+      InstallOnAndroid(self.device, download['trichrome'])
     else:
-      trichrome = self._get_apk_filename(prefer_64bit=False)
-      trichrome_library = self._get_library_filename(prefer_64bit=False)
-    return {
-        'trichrome': self._get_archive_path(revision, trichrome),
-        'trichrome_library': self._get_archive_path(revision,
-                                                    trichrome_library),
-    }
-
-  def _install_revision(self, download, tempdir):
-    if not isinstance(download, dict):
-      raise Exception("Trichrome should download multiple files from GCS.")
-    # AndroidRelease build downloads the apks directly from GCS bucket.
-    # Trichrome need to install the trichrome_library first.
-    InstallOnAndroid(self.device, download['trichrome_library'])
-    InstallOnAndroid(self.device, download['trichrome'])
+      InstallOnAndroid(self.device, download)
 
 
-class AndroidDesktopTrichromeReleaseBuild(AndroidTrichromeReleaseBuild):
-
-  def __init__(self, *args, **kwargs):
-    super().__init__(*args, **kwargs)
+class AndroidDesktopReleaseBuild(AndroidReleaseBuild):
 
   def _get_apk_filename(self, *args, **kwargs):
     apk_filename = super()._get_apk_filename(*args, **kwargs)
-    # android-desktop release APKs have a different naming scheme:
-    # http://shortn/_LC4UqvdoeC.
     return apk_filename.replace('Google64', 'GoogleDesktop64')
 
   def _get_library_filename(self, prefer_64bit=True):
@@ -1505,21 +1475,11 @@
       raise BisectException('chrome debug build is not supported for %s' %
                             self.platform)
     library_filename = super()._get_library_filename(prefer_64bit)
-    # android-desktop release APKs have a different naming scheme:
-    # http://shortn/_LC4UqvdoeC.
-    return library_filename.replace('Google64', 'GoogleDesktop64')
-
-
-class AndroidTrichromeOfficialBuild(AndroidTrichromeMixin, OfficialBuild):
-
-  def __init__(self, options):
-    super().__init__(options)
-
-  def _get_apk_mapping(self, prefer_64bit=True):
-    return {
-        k: v.replace(".apks", ".minimal.apks")
-        for k, v in super()._get_apk_mapping(prefer_64bit).items()
-    }
+    if library_filename:
+      # android-desktop release APKs have a different naming scheme:
+      # http://shortn/_LC4UqvdoeC.
+      return library_filename.replace('Google64', 'GoogleDesktop64')
+    return None
 
 
 class LinuxReleaseBuild(ReleaseBuild):
@@ -1533,7 +1493,10 @@
 
 
 class AndroidOfficialBuild(AndroidBuildMixin, OfficialBuild):
-  pass
+
+  def _get_apk_mapping(self, prefer_64bit=True):
+    mapping = super()._get_apk_mapping(prefer_64bit)
+    return {k: v.replace(".apks", ".minimal.apks") for k, v in mapping.items()}
 
 
 class AndroidSnapshotBuild(AndroidBuildMixin, SnapshotBuild):
@@ -1678,10 +1641,8 @@
 
 def create_archive_build(options):
   if options.build_type == 'release':
-    if options.archive == 'android-arm64-high':
-      return AndroidTrichromeReleaseBuild(options)
-    elif options.archive == 'android-desktop-x64':
-      return AndroidDesktopTrichromeReleaseBuild(options)
+    if options.archive == 'android-desktop-x64':
+      return AndroidDesktopReleaseBuild(options)
     elif options.archive.startswith('android'):
       return AndroidReleaseBuild(options)
     elif options.archive.startswith('linux'):
@@ -1692,9 +1653,7 @@
       return IOSReleaseBuild(options)
     return ReleaseBuild(options)
   elif options.build_type == 'official':
-    if options.archive in ('android-arm64-high', 'android-desktop-x64'):
-      return AndroidTrichromeOfficialBuild(options)
-    elif options.archive.startswith('android'):
+    if options.archive.startswith('android'):
       return AndroidOfficialBuild(options)
     return OfficialBuild(options)
   elif options.build_type == 'asan':
diff --git a/tools/bisect_test.py b/tools/bisect_test.py
index 0cd3d84..cd69d56 100755
--- a/tools/bisect_test.py
+++ b/tools/bisect_test.py
@@ -1125,8 +1125,7 @@
   @patch('glob.glob', return_value=['Monochrome.apk'])
   def test_install_revision(self, mock_glob, mock_InstallOnAndroid, mock_unzip):
     options = bisect_builds.ParseCommandLine([
-        '-a', 'android-arm64', '-g', '1313161', '-b', '1313210', '--apk',
-        'chrome'
+        '-a', 'android-arm', '-g', '1313161', '-b', '1313210', '--apk', 'chrome'
     ])
     build = bisect_builds.create_archive_build(options)
     self.assertIsInstance(build, bisect_builds.AndroidSnapshotBuild)
@@ -1145,8 +1144,7 @@
   def test_install_revision_with_show_available_apks(self, mock_glob,
                                                      mock_stdout, mock_unzip):
     options = bisect_builds.ParseCommandLine([
-        '-a', 'android-arm64', '-g', '1313161', '-b', '1313210', '--apk',
-        'chrome'
+        '-a', 'android-arm', '-g', '1313161', '-b', '1313210', '--apk', 'chrome'
     ])
     build = bisect_builds.create_archive_build(options)
     self.assertIsInstance(build, bisect_builds.AndroidSnapshotBuild)
@@ -1163,8 +1161,7 @@
   def test_install_revision_with_show_unknown_apks(self, mock_glob, mock_stdout,
                                                    mock_unzip):
     options = bisect_builds.ParseCommandLine([
-        '-a', 'android-arm64', '-g', '1313161', '-b', '1313210', '--apk',
-        'chrome'
+        '-a', 'android-arm', '-g', '1313161', '-b', '1313210', '--apk', 'chrome'
     ])
     build = bisect_builds.create_archive_build(options)
     self.assertIsInstance(build, bisect_builds.AndroidSnapshotBuild)
@@ -1174,7 +1171,8 @@
                   mock_stdout.getvalue())
     self.assertIn("unknown.apks", mock_stdout.getvalue())
 
-class AndroidTrichromeReleaseBuildTest(AndroidBuildTest):
+
+class AndroidArm64HighReleaseBuildTest(AndroidBuildTest):
 
   def setUp(self):
     super().setUp()
@@ -1197,7 +1195,7 @@
         '129.0.6626.0', '-b', '129.0.6628.0', '--no-local-cache'
     ])
     build = bisect_builds.create_archive_build(options)
-    self.assertIsInstance(build, bisect_builds.AndroidTrichromeReleaseBuild)
+    self.assertIsInstance(build, bisect_builds.AndroidReleaseBuild)
     self.assertEqual(build.get_rev_list(),
                      ['129.0.6626.0', '129.0.6627.0', '129.0.6628.0'])
     print(mock_GsutilList.call_args_list)
@@ -1212,14 +1210,15 @@
                                     ignore_fail=True)
     self.assertEqual(mock_GsutilList.call_count, 2)
 
-  def test_should_raise_exception_for_PIE(self):
+  def test_should_work_for_PIE(self):
     options = bisect_builds.ParseCommandLine([
         '-r', '-a', 'android-arm64-high', '--apk', 'chrome_stable', '-g',
         '129.0.6626.0', '-b', '129.0.6667.0'
     ])
     self.set_sdk_level(bisect_builds.version_codes.PIE)
-    with self.assertRaises(bisect_builds.BisectException):
-      bisect_builds.create_archive_build(options)
+    build = bisect_builds.create_archive_build(options)
+    self.assertIsInstance(build, bisect_builds.AndroidReleaseBuild)
+    self.assertEqual(build.binary_name, 'MonochromeStable.apk')
 
   def test_get_download_url(self):
     options = bisect_builds.ParseCommandLine([
@@ -1227,7 +1226,7 @@
         '129.0.6626.0', '-b', '129.0.6628.0'
     ])
     build = bisect_builds.create_archive_build(options)
-    self.assertIsInstance(build, bisect_builds.AndroidTrichromeReleaseBuild)
+    self.assertIsInstance(build, bisect_builds.AndroidReleaseBuild)
     download_urls = build.get_download_url('129.0.6626.0')
     self.maxDiff = 1000
     self.assertDictEqual(
@@ -1251,13 +1250,13 @@
         '129.0.6626.0', '-b', '129.0.6628.0'
     ])
     build = bisect_builds.create_archive_build(options)
-    self.assertIsInstance(build, bisect_builds.AndroidTrichromeReleaseBuild)
+    self.assertIsInstance(build, bisect_builds.AndroidReleaseBuild)
     build._install_revision(downloads, 'tmp-dir')
     mock_InstallOnAndroid.assert_any_call(self.device, 'some-file.apks')
     mock_InstallOnAndroid.assert_any_call(self.device, 'file2.apk')
 
 
-class AndroidTrichromeOfficialBuildTest(AndroidBuildTest):
+class AndroidArm64HighOfficialBuildTest(AndroidBuildTest):
 
   @maybe_patch('bisect-builds.GsutilList',
                return_value=[
@@ -1270,7 +1269,7 @@
         '-b', '1334380', '--no-local-cache'
     ])
     build = bisect_builds.create_archive_build(options)
-    self.assertIsInstance(build, bisect_builds.AndroidTrichromeOfficialBuild)
+    self.assertIsInstance(build, bisect_builds.AndroidOfficialBuild)
     self.assertEqual(build.get_rev_list(),
                      [1334339, 1334342, 1334344, 1334345, 1334356])
     mock_GsutilList.assert_called_once_with(
@@ -1283,7 +1282,7 @@
         '-b', '1334380'
     ])
     build = bisect_builds.create_archive_build(options)
-    self.assertIsInstance(build, bisect_builds.AndroidTrichromeOfficialBuild)
+    self.assertIsInstance(build, bisect_builds.AndroidOfficialBuild)
     self.assertEqual(
         build.get_download_url(1334338),
         'gs://chrome-test-builds/official-by-commit'
@@ -1302,7 +1301,7 @@
         '-b', '1334380'
     ])
     build = bisect_builds.create_archive_build(options)
-    self.assertIsInstance(build, bisect_builds.AndroidTrichromeOfficialBuild)
+    self.assertIsInstance(build, bisect_builds.AndroidOfficialBuild)
     build._install_revision('download.zip', 'tmp-dir')
     mock_UnzipFilenameToDir.assert_called_once_with('download.zip', 'tmp-dir')
     mock_InstallOnAndroid.assert_any_call(
@@ -1326,7 +1325,7 @@
         '-b', '1334380'
     ])
     build = bisect_builds.create_archive_build(options)
-    self.assertIsInstance(build, bisect_builds.AndroidTrichromeOfficialBuild)
+    self.assertIsInstance(build, bisect_builds.AndroidOfficialBuild)
     with self.assertRaises(bisect_builds.BisectException):
       build._install_revision('download.zip', 'tmp-dir')
     self.assertIn("The list of available --apk:", mock_stdout.getvalue())
@@ -1343,7 +1342,7 @@
         '-b', '1334380'
     ])
     build = bisect_builds.create_archive_build(options)
-    self.assertIsInstance(build, bisect_builds.AndroidTrichromeOfficialBuild)
+    self.assertIsInstance(build, bisect_builds.AndroidOfficialBuild)
     download_job = build.get_download_job(1334339)
     zip_file = download_job.start().wait_for()
     with tempfile.TemporaryDirectory(prefix='bisect_tmp') as tempdir:
@@ -1383,7 +1382,7 @@
 
     build = bisect_builds.create_archive_build(options)
 
-    self.assertIsInstance(build, bisect_builds.AndroidTrichromeOfficialBuild)
+    self.assertIsInstance(build, bisect_builds.AndroidOfficialBuild)
     download_job = build.get_download_job(1334339)
     zip_file = download_job.start().wait_for()
     with tempfile.TemporaryDirectory(prefix='bisect_tmp') as tempdir:
@@ -1409,7 +1408,7 @@
                                                       mock_InstallOnAndroid,
                                                       mock_unzip):
     options = bisect_builds.ParseCommandLine([
-        'o', '-a', 'android-arm64', '-g', '1313161', '-b', '1313210', '--apk',
+        'o', '-a', 'android-arm', '-g', '1313161', '-b', '1313210', '--apk',
         'webview'
     ])
     build = bisect_builds.create_archive_build(options)
@@ -1934,5 +1933,82 @@
     mock_fetch_json.assert_not_called()
 
 
+class AndroidDesktopReleaseBuildTest(AndroidBuildTest):
+
+  def setUp(self):
+    super().setUp()
+    self.set_sdk_level(bisect_builds.version_codes.Q)
+
+  @maybe_patch(
+      'bisect-builds.GsutilList',
+      side_effect=
+      [[
+          'gs://chrome-unsigned/android-B0urB0N/%s/' % x for x in [
+              '129.0.6626.0', '129.0.6626.1', '129.0.6627.0', '129.0.6627.1',
+              '129.0.6628.0'
+          ]
+      ],
+       [
+           'gs://chrome-unsigned/android-B0urB0N/129.0.6626.0/desktop-x86_64/TrichromeChromeGoogleDesktop64Stable.apks',
+           'gs://chrome-unsigned/android-B0urB0N/129.0.6626.1/desktop-x86_64/TrichromeChromeGoogleDesktop64Stable.apks',
+           'gs://chrome-unsigned/android-B0urB0N/129.0.6627.0/desktop-x86_64/TrichromeChromeGoogleDesktop64Stable.apks',
+           'gs://chrome-unsigned/android-B0urB0N/129.0.6627.1/desktop-x86_64/TrichromeChromeGoogleDesktop64Stable.apks',
+           'gs://chrome-unsigned/android-B0urB0N/129.0.6628.0/desktop-x86_64/TrichromeChromeGoogleDesktop64Stable.apks'
+       ]])
+  def test_get_rev_list(self, mock_GsutilList):
+    options = bisect_builds.ParseCommandLine([
+        '-r', '-a', 'android-desktop-x64', '--apk', 'chrome_stable', '-g',
+        '129.0.6626.0', '-b', '129.0.6628.0'
+    ])
+    build = bisect_builds.create_archive_build(options)
+    self.assertIsInstance(build, bisect_builds.AndroidDesktopReleaseBuild)
+    self.assertEqual(build.get_rev_list(), [
+        '129.0.6626.0', '129.0.6626.1', '129.0.6627.0', '129.0.6627.1',
+        '129.0.6628.0'
+    ])
+    mock_GsutilList.assert_has_calls([
+        call('gs://chrome-unsigned/android-B0urB0N'),
+        call(
+            'gs://chrome-unsigned/android-B0urB0N/129.0.6626.0/desktop-x86_64/TrichromeChromeGoogleDesktop64Stable.apks',
+            'gs://chrome-unsigned/android-B0urB0N/129.0.6626.1/desktop-x86_64/TrichromeChromeGoogleDesktop64Stable.apks',
+            'gs://chrome-unsigned/android-B0urB0N/129.0.6627.0/desktop-x86_64/TrichromeChromeGoogleDesktop64Stable.apks',
+            'gs://chrome-unsigned/android-B0urB0N/129.0.6627.1/desktop-x86_64/TrichromeChromeGoogleDesktop64Stable.apks',
+            'gs://chrome-unsigned/android-B0urB0N/129.0.6628.0/desktop-x86_64/TrichromeChromeGoogleDesktop64Stable.apks',
+            ignore_fail=True)
+    ])
+
+  def test_get_download_url(self):
+    options = bisect_builds.ParseCommandLine([
+        '-r', '-a', 'android-desktop-x64', '--apk', 'chrome_stable', '-g',
+        '129.0.6626.0', '-b', '129.0.6628.0'
+    ])
+    build = bisect_builds.create_archive_build(options)
+    self.assertIsInstance(build, bisect_builds.AndroidDesktopReleaseBuild)
+    download_urls = build.get_download_url('129.0.6626.0')
+    self.assertDictEqual(
+        download_urls, {
+            'trichrome':
+            ('gs://chrome-unsigned/android-B0urB0N/129.0.6626.0/desktop-x86_64/'
+             'TrichromeChromeGoogleDesktop64Stable.apks'),
+            'trichrome_library':
+            ('gs://chrome-unsigned/android-B0urB0N/129.0.6626.0/desktop-x86_64/'
+             'TrichromeLibraryGoogleDesktop64Stable.apk'),
+        })
+
+  @patch('bisect-builds.InstallOnAndroid')
+  def test_install_revision(self, mock_InstallOnAndroid):
+    downloads = {
+        'trichrome': 'some-file.apks',
+        'trichrome_library': 'file2.apk',
+    }
+    options = bisect_builds.ParseCommandLine([
+        '-r', '-a', 'android-desktop-x64', '--apk', 'chrome_stable', '-g',
+        '129.0.6626.0', '-b', '129.0.6628.0'
+    ])
+    build = bisect_builds.create_archive_build(options)
+    self.assertIsInstance(build, bisect_builds.AndroidDesktopReleaseBuild)
+    build._install_revision(downloads, 'tmp-dir')
+    mock_InstallOnAndroid.assert_any_call(self.device, 'some-file.apks')
+    mock_InstallOnAndroid.assert_any_call(self.device, 'file2.apk')
 if __name__ == '__main__':
   unittest.main()
diff --git a/tools/idl_parser/idl_parser.py b/tools/idl_parser/idl_parser.py
index 69b1bb7..6dfde25 100755
--- a/tools/idl_parser/idl_parser.py
+++ b/tools/idl_parser/idl_parser.py
@@ -1050,11 +1050,13 @@
   #    [ identifier ]
   #    [ identifier ( ArgumentList ) ]
   #    [ identifier = identifier ]
+  #    [ identifier = * ]
   #    [ identifier = ( IdentifierList ) ]
   #    [ identifier = identifier ( ArgumentList ) ]
+  #    [ identifier = integer ]
   #    [ identifier = StringLiteral ]
   #    [ identifier = ( StringList ) ]
-  # The first five patterns are specified in the Web IDL spec and the last two
+  # The first seven patterns are specified in the Web IDL spec and the last two
   # patterns are Blink's custom extension to support [ReflectOnly].
   def p_ExtendedAttribute(self, p):
     """ExtendedAttribute : ExtendedAttributeNoArgs
@@ -1063,6 +1065,7 @@
                          | ExtendedAttributeWildcard
                          | ExtendedAttributeIdentList
                          | ExtendedAttributeNamedArgList
+                         | ExtendedAttributeInteger
                          | ExtendedAttributeStringLiteral
                          | ExtendedAttributeStringLiteralList"""
     p[0] = p[1]
@@ -1113,6 +1116,11 @@
     value = self.BuildNamed('Call', p, 3, args)
     p[0] = self.BuildNamed('ExtAttribute', p, 1, value)
 
+  def p_ExtendedAttributeInteger(self, p):
+    """ExtendedAttributeInteger : identifier '=' integer"""
+    value = self.BuildAttribute('VALUE', p[3])
+    p[0] = self.BuildNamed('ExtAttribute', p, 1, value)
+
   # Blink extension: Add support for string literal Extended Attribute values
   def p_ExtendedAttributeStringLiteral(self, p):
     """ExtendedAttributeStringLiteral : identifier '=' StringLiteral"""
diff --git a/tools/idl_parser/idl_parser_test.py b/tools/idl_parser/idl_parser_test.py
index 001828d..1c2be04 100755
--- a/tools/idl_parser/idl_parser_test.py
+++ b/tools/idl_parser/idl_parser_test.py
@@ -281,6 +281,17 @@
     self.assertEqual('Window', identifierList[0])
     self.assertEqual('Worker', identifierList[1])
 
+  def testIntegerValueInExtendedAttribute(self):
+    extended_attribute_text = '[ReflectDefault=2]'
+    attributes = self._ParseIdlWithExtendedAttributes(extended_attribute_text)
+    self.assertEqual('ExtAttributes', attributes.GetClass())
+    self.assertEqual(1, len(attributes.GetChildren()))
+    attribute = attributes.GetChildren()[0]
+    self.assertEqual('ExtAttribute', attribute.GetClass())
+    self.assertEqual('ReflectDefault', attribute.GetName())
+    value = attribute.GetProperty('VALUE')
+    self.assertEqual('2', value)
+
   def testErrorTrailingComma(self):
     extended_attribute_text = '[Replacable, Exposed=(Window,Worker),]'
     error = self._ParseIdlWithExtendedAttributes(extended_attribute_text)
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 4c0d6dd..a018829 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -27260,6 +27260,13 @@
   </description>
 </action>
 
+<action name="MobileGeminiFloatyExpandedToDismissed">
+  <owner>joemerramos@google.com</owner>
+  <description>
+    The user dismissed the Gemini floaty from an expanded state. iOS only.
+  </description>
+</action>
+
 <action name="MobileGeminiFREConsentAccept">
   <owner>kanouche@google.com</owner>
   <owner>bling-alchemy@google.com</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 3dae6d2..bfc3eb17 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -8283,6 +8283,7 @@
   <int value="-2077268643" label="disable-device-enumeration"/>
   <int value="-2076848010" label="NtpComposebox:disabled"/>
   <int value="-2076313806" label="TrustTokens:disabled"/>
+  <int value="-2076121369" label="NtpMvcRefactor:disabled"/>
   <int value="-2075870708" label="MediaRemotingEncrypted:disabled"/>
   <int value="-2075807193" label="enable-webusb-on-any-origin"/>
   <int value="-2075725205" label="disable-new-zip-unpacker"/>
@@ -11655,6 +11656,7 @@
   <int value="-949137285" label="EnableRootNsDnsProxy:enabled"/>
   <int value="-948930847" label="EnableOopPrintDrivers:enabled"/>
   <int value="-948684341" label="OmniboxBlurWithEscape:enabled"/>
+  <int value="-948678625" label="NtpMvcRefactor:enabled"/>
   <int value="-948256052" label="EnableInputInDiagnosticsApp:enabled"/>
   <int value="-948067160" label="AXTreeFixing:disabled"/>
   <int value="-947643308" label="EnableTouchscreensInDiagnosticsApp:disabled"/>
@@ -13996,6 +13998,7 @@
   <int value="-137716319" label="ExtensionManifestV2Unsupported:enabled"/>
   <int value="-137394236" label="TabStripContextMenuAndroid:disabled"/>
   <int value="-137303226" label="enable-chromevox-developer-option"/>
+  <int value="-136974597" label="DefaultBrowserPromptSurfaces:disabled"/>
   <int value="-136663703" label="Compose:enabled"/>
   <int value="-136485076" label="NtpModules:disabled"/>
   <int value="-135584721"
@@ -16342,6 +16345,7 @@
   <int value="665320858" label="WebViewHitTestInBlinkOnTouchStart:disabled"/>
   <int value="665409384"
       label="AutofillToolkitViewsCreditCardDialogsMac:enabled"/>
+  <int value="665421480" label="GlicChromeStatusIcon:enabled"/>
   <int value="665647051" label="DiscountConsentV2:enabled"/>
   <int value="666163273" label="WebMachineLearningNeuralNetwork:enabled"/>
   <int value="666428855" label="MediaRemotingWithoutFullscreen:enabled"/>
@@ -19293,6 +19297,7 @@
   <int value="1664401033" label="ColorCorrectRendering:enabled"/>
   <int value="1664463407" label="FirstPartySets:enabled"/>
   <int value="1664710107" label="BorealisScaleClientByDPI:enabled"/>
+  <int value="1665076479" label="GlicChromeStatusIcon:disabled"/>
   <int value="1665349789" label="spurious-power-button-window"/>
   <int value="1665400247" label="OsSettingsDeepLinking:enabled"/>
   <int value="1665430464" label="force-control-face-ae"/>
@@ -19672,6 +19677,7 @@
   <int value="1787171971" label="UserEducationExperienceVersion2:enabled"/>
   <int value="1787279386" label="VirtualKeyboardMultitouch:enabled"/>
   <int value="1787572807" label="PrefixWebAppWindowsWithAppName:enabled"/>
+  <int value="1788097134" label="DefaultBrowserPromptSurfaces:enabled"/>
   <int value="1788323093" label="AuxiliaryNavigationStaysInPWA:disabled"/>
   <int value="1789517771" label="MacV2Sandbox:enabled"/>
   <int value="1789793147" label="HTTPSServerPreviewsUsingURLLoader:disabled"/>
@@ -23941,9 +23947,10 @@
   <int value="0" label="FEATURE_NAME_UNSPECIFIED"/>
   <int value="3" label="FEATURE_NAME_DEMO_GEMINI_GENERATE_CONTENT"/>
   <int value="700" label="FEATURE_NAME_CHROME_ZERO_STATE_SUGGESTION"/>
+  <int value="701" label="FEATURE_NAME_CHROME_FORMS_AI"/>
 </enum>
 
-<!-- LINT.ThenChange(//components/private_ai/proto/legion.proto:FeatureName) -->
+<!-- LINT.ThenChange(//components/private_ai/proto/private_ai.proto:FeatureName) -->
 
 <enum name="ProbeResult">
   <int value="0" label="No internet"/>
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml
index 9d265ee8..93563d6 100644
--- a/tools/metrics/histograms/metadata/accessibility/histograms.xml
+++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -3331,6 +3331,17 @@
   </summary>
 </histogram>
 
+<histogram name="Accessibility.ReadAnything.SidePanelTriggeredByEmptyState"
+    enum="ReadAnythingOpenTrigger" expires_after="2027-01-01">
+  <owner>martinglopez@google.com</owner>
+  <owner>chrome-irm-devs@google.com</owner>
+  <summary>
+    Records when Immersive Reading Mode opens in side panel mode because the
+    distillation was empty. This metric captures the original trigger for
+    opening Reading Mode (e.g. Omnibox, Context Menu) or the Toggle trigger.
+  </summary>
+</histogram>
+
 <histogram name="Accessibility.ReadAnything.SpeechError"
     enum="ReadAnythingSpeechError" expires_after="2026-08-23">
   <owner>lwinston@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/blink/enums.xml b/tools/metrics/histograms/metadata/blink/enums.xml
index 67d4474..678fcf9 100644
--- a/tools/metrics/histograms/metadata/blink/enums.xml
+++ b/tools/metrics/histograms/metadata/blink/enums.xml
@@ -6167,7 +6167,7 @@
   <int value="5546" label="InputParsedParentSelect"/>
   <int value="5547" label="InputParsedAncestorSelect"/>
   <int value="5548" label="CSSSelectorPseudoHasSlotted"/>
-  <int value="5549" label="SelectMultipleShowPopup"/>
+  <int value="5549" label="OBSOLETE_SelectMultipleShowPopup"/>
   <int value="5550" label="SharedWorkerExtendedLifetimeFeatureEnabled"/>
   <int value="5551" label="SharedWorkerExtendedLifetimeIsTrue"/>
   <int value="5552" label="OBSOLETE_EditContextTextFormatUpdateAddListener"/>
@@ -6431,6 +6431,8 @@
   <int value="5794" label="LanguageModel_ContextWindow"/>
   <int value="5795" label="LanguageModel_MeasureContextUsage"/>
   <int value="5796" label="V8WindowClient_Navigate_Method"/>
+  <int value="5797" label="LanguageModel_OnQuotaOverflow"/>
+  <int value="5798" label="LanguageModel_OnContextOverflow"/>
 </enum>
 
 <!-- LINT.ThenChange(//third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom:WebFeature) -->
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml
index 0715e11..bf24836 100644
--- a/tools/metrics/histograms/metadata/blink/histograms.xml
+++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -1913,7 +1913,7 @@
 </histogram>
 
 <histogram name="Blink.FedCm.LifecycleStateFailureReason"
-    enum="FedCmLifecycleStateFailureReason" expires_after="2026-03-22">
+    enum="FedCmLifecycleStateFailureReason" expires_after="2026-09-22">
   <owner>cbiesinger@chromium.org</owner>
   <owner>web-identity-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/glic/enums.xml b/tools/metrics/histograms/metadata/glic/enums.xml
index 6ec0c187..97fee15 100644
--- a/tools/metrics/histograms/metadata/glic/enums.xml
+++ b/tools/metrics/histograms/metadata/glic/enums.xml
@@ -497,6 +497,7 @@
   <int value="16" label="Automatically opened by contextual cueing"/>
   <int value="17" label="User clicked the summarize button in the PDF viewer"/>
   <int value="18" label="From navigation capture"/>
+  <int value="19" label="Automatically opened for a PDF"/>
 </enum>
 
 <!-- LINT.ThenChange(//chrome/browser/glic/host/glic.mojom:InvocationSource) -->
@@ -679,6 +680,10 @@
   <int value="74" label="navigation capture, attached, audio mode."/>
   <int value="75" label="navigation capture, detached, text mode."/>
   <int value="76" label="navigation capture, detached, audio mode."/>
+  <int value="77" label="Auto-opened for PDF, attached, text mode."/>
+  <int value="78" label="Auto-opened for PDF, attached, audio mode."/>
+  <int value="79" label="Auto-opened for PDF, detached, text mode."/>
+  <int value="80" label="Auto-opened for PDF, detached, audio mode."/>
 </enum>
 
 <!-- LINT.ThenChange(//chrome/browser/glic/glic_metrics.h:ResponseSegmentation) -->
diff --git a/tools/metrics/histograms/metadata/ios/enums.xml b/tools/metrics/histograms/metadata/ios/enums.xml
index b0d3dab..888b24fa 100644
--- a/tools/metrics/histograms/metadata/ios/enums.xml
+++ b/tools/metrics/histograms/metadata/ios/enums.xml
@@ -124,6 +124,17 @@
 
 <!-- LINT.ThenChange(//ios/chrome/browser/fullscreen/ui_bundled/fullscreen_metrics.h:FullscreenModeTransitionReason) -->
 
+<!-- LINT.IfChange(GeminiViewState) -->
+
+<enum name="GeminiViewState">
+  <int value="0" label="Unknown"/>
+  <int value="1" label="Hidden"/>
+  <int value="2" label="Collapsed"/>
+  <int value="3" label="Expanded"/>
+</enum>
+
+<!-- LINT.ThenChange(/ios/public/provider/chrome/browser/bwg/bwg_api.h:GeminiViewState) -->
+
 <enum name="GeolocationAPI">
   <int value="0" label="Clear Watch"/>
   <int value="1" label="Get Current Position"/>
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml
index 24c9531..d2bed9ba 100644
--- a/tools/metrics/histograms/metadata/ios/histograms.xml
+++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -2567,6 +2567,13 @@
   </summary>
 </histogram>
 
+<histogram name="IOS.Gemini.Floaty.DismissedState" enum="GeminiViewState"
+    expires_after="2027-02-25">
+  <owner>joemerramos@google.com</owner>
+  <owner>bling-alchemy-eng@google.com</owner>
+  <summary>Records the state of the floaty when it is dismissed.</summary>
+</histogram>
+
 <histogram name="IOS.Gemini.Floaty.HiddenFromSource"
     enum="IOSGeminiFloatyUpdateSource" expires_after="2027-01-25">
   <owner>joemerramos@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml
index 7d78b56..4141154 100644
--- a/tools/metrics/histograms/metadata/net/histograms.xml
+++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -2623,30 +2623,6 @@
 </histogram>
 
 <histogram
-    name="Net.DNS.DnsTransaction.SecureNotValidated.{DohProviderId}FailureTime"
-    units="ms" expires_after="2024-07-22">
-  <owner>awillia@chromium.org</owner>
-  <owner>src/net/dns/OWNERS</owner>
-  <summary>
-    Duration of time taken by a secure DnsTransaction to a DoH server that is
-    unavailable or has unknown availability to fail. These transactions may be
-    probe queries or queries issued in the secure DNS mode. {DohProviderId}
-  </summary>
-</histogram>
-
-<histogram
-    name="Net.DNS.DnsTransaction.SecureNotValidated.{DohProviderId}SuccessTime"
-    units="ms" expires_after="2024-07-22">
-  <owner>awillia@chromium.org</owner>
-  <owner>src/net/dns/OWNERS</owner>
-  <summary>
-    Duration of time taken by a secure DnsTransaction to a DoH server that is
-    unavailable or has unknown availability to succeed. These transactions may
-    be probe queries or queries issued in the secure DNS mode. {DohProviderId}
-  </summary>
-</histogram>
-
-<histogram
     name="Net.DNS.DnsTransaction.SecureValidated.{DohProviderId}FailureError"
     enum="NetErrorCodes" expires_after="2026-07-26">
   <owner>awillia@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/ui/enums.xml b/tools/metrics/histograms/metadata/ui/enums.xml
index eb6eb1b..cfa61f9 100644
--- a/tools/metrics/histograms/metadata/ui/enums.xml
+++ b/tools/metrics/histograms/metadata/ui/enums.xml
@@ -471,6 +471,9 @@
   <int value="79" label="UMA_FUSEBOX_UPLOAD_FAILED"/>
   <int value="80" label="UMA_BOOKMARK_LINK_COPIED"/>
   <int value="81" label="UMA_BOOKMARK_LINK_COPIED_NON_SELECTION"/>
+  <int value="82" label="UMA_CROSS_DEVICE_SETTING_IMPORT"/>
+  <int value="83" label="UMA_CROSS_DEVICE_SETTING_UNDO"/>
+  <int value="84" label="UMA_CROSS_DEVICE_SETTING_REDO"/>
 </enum>
 
 <enum name="WebUIPreloadReason">
@@ -827,6 +830,7 @@
   <int value="-359703631" label="chrome://slow_trace/"/>
   <int value="-336117866" label="chrome://focus-mode-media/"/>
   <int value="-332876060" label="chrome://autofill-ml-internals/"/>
+  <int value="-251863235" label="chrome-untrusted://glic/"/>
   <int value="-245337017" label="chrome://user-actions/"/>
   <int value="-233401490" label="chrome://accessory-update/"/>
   <int value="-222190329" label="chrome://dino/"/>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index bc87cc2..a8675f8 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@
             "full_remote_path": "perfetto-luci-artifacts/v52.0/linux-arm64/trace_processor_shell"
         },
         "win": {
-            "hash": "511288f893c47ae02e3534420eee6dcc6a452533",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/c82fb577c5b0e0100da838161757d37851514ffb/trace_processor_shell.exe"
+            "hash": "81cc9918638d2b95e22d9b721f857208530c0604",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/ea8d0aaeb1e22f03fa0498c42e3f86f3daf753f2/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "46d798c1864490cbb2ee053d6eda436184470e69",
diff --git a/ui/accessibility/ax_event_generator.cc b/ui/accessibility/ax_event_generator.cc
index 5e0d7a4..8fe1cacc 100644
--- a/ui/accessibility/ax_event_generator.cc
+++ b/ui/accessibility/ax_event_generator.cc
@@ -63,6 +63,22 @@
   return ignored_changed_states[static_cast<size_t>(state)];
 }
 
+// Returns the node on which text-attribute and marker events should be fired.
+// On a native text field, markers are associated with children not exposed on
+// any platform, so we adjust the target to the text field ancestor. For richly
+// editable nodes, the node itself is the target. Returns nullptr if neither
+// applies.
+AXNode* GetTextAttributeTarget(AXNode* node) {
+  if (!node) {
+    return nullptr;
+  }
+  AXNode* target = node->GetTextFieldAncestor();
+  if (!target && node->HasState(ax::mojom::State::kRichlyEditable)) {
+    target = node;
+  }
+  return target;
+}
+
 }  // namespace
 
 //
@@ -796,18 +812,99 @@
     case ax::mojom::IntListAttribute::kLabelledbyIds:
       AddEvent(node, Event::LABELED_BY_CHANGED);
       break;
-    case ax::mojom::IntListAttribute::kMarkerEnds:
-    case ax::mojom::IntListAttribute::kMarkerStarts:
-    case ax::mojom::IntListAttribute::kMarkerTypes:
-      // On a native text field, the spelling- and grammar-error markers are
-      // associated with children not exposed on any platform. Therefore, we
-      // adjust the node we fire that event on here.
-      if (AXNode* text_field = node->GetTextFieldAncestor()) {
-        AddEvent(text_field, Event::TEXT_ATTRIBUTE_CHANGED);
-      } else if (node->HasState(ax::mojom::State::kRichlyEditable)) {
-        AddEvent(node, Event::TEXT_ATTRIBUTE_CHANGED);
+    case ax::mojom::IntListAttribute::kMarkerTypes: {
+      AXNode* target = GetTextAttributeTarget(node);
+      if (!target) {
+        break;
+      }
+      AddEvent(target, Event::TEXT_ATTRIBUTE_CHANGED);
+
+      // If there was a removal, don't fire events.
+      if (old_value.size() > new_value.size()) {
+        break;
+      }
+
+      // Fire specific marker events only for types that were newly added
+      // (not for removals).
+      int32_t added_types = 0;
+      size_t min_size = std::min(old_value.size(), new_value.size());
+      for (size_t i = 0; i < min_size; ++i) {
+        // Bits present in new but not old are newly added.
+        added_types |= (new_value[i] & ~old_value[i]);
+      }
+      // Entries only in new_value are entirely new.
+      for (size_t i = min_size; i < new_value.size(); ++i) {
+        added_types |= new_value[i];
+      }
+      if (added_types &
+          static_cast<int32_t>(ax::mojom::MarkerType::kSpelling)) {
+        AddEvent(target, Event::SPELLING_MARKER_CHANGED);
+      }
+      if (added_types & static_cast<int32_t>(ax::mojom::MarkerType::kGrammar)) {
+        AddEvent(target, Event::GRAMMAR_MARKER_CHANGED);
+      }
+      // We skip highlight marker case here because it's handled by highlight
+      // types.
+      break;
+    }
+    case ax::mojom::IntListAttribute::kHighlightTypes: {
+      AXNode* target = GetTextAttributeTarget(node);
+      if (!target) {
+        break;
+      }
+      AddEvent(target, Event::TEXT_ATTRIBUTE_CHANGED);
+
+      // If there was a removal, don't fire events.
+      if (old_value.size() > new_value.size()) {
+        break;
+      }
+
+      // Fire specific marker events only for highlight types that were
+      // newly added (not for removals).
+      bool spelling_added = false;
+      bool grammar_added = false;
+      bool highlight_added = false;
+      size_t min_size = std::min(old_value.size(), new_value.size());
+      auto flag_highlight_type = [&](int32_t ht) {
+        auto t = static_cast<ax::mojom::HighlightType>(ht);
+        if (t == ax::mojom::HighlightType::kSpellingError) {
+          spelling_added = true;
+        } else if (t == ax::mojom::HighlightType::kGrammarError) {
+          grammar_added = true;
+        } else if (t == ax::mojom::HighlightType::kHighlight) {
+          highlight_added = true;
+        }
+      };
+      // For overlapping indices, only flag the new type when it differs.
+      for (size_t i = 0; i < min_size; ++i) {
+        if (old_value[i] != new_value[i]) {
+          flag_highlight_type(new_value[i]);
+        }
+      }
+      // Entries only in new_value were added.
+      for (size_t i = min_size; i < new_value.size(); ++i) {
+        flag_highlight_type(new_value[i]);
+      }
+      if (spelling_added) {
+        AddEvent(target, Event::SPELLING_MARKER_CHANGED);
+      }
+      if (grammar_added) {
+        AddEvent(target, Event::GRAMMAR_MARKER_CHANGED);
+      }
+      if (highlight_added) {
+        AddEvent(target, Event::HIGHLIGHT_MARKER_CHANGED);
       }
       break;
+    }
+    case ax::mojom::IntListAttribute::kMarkerEnds:
+    case ax::mojom::IntListAttribute::kMarkerStarts: {
+      AXNode* target = GetTextAttributeTarget(node);
+      if (!target) {
+        break;
+      }
+      AddEvent(target, Event::TEXT_ATTRIBUTE_CHANGED);
+      break;
+    }
     case ax::mojom::IntListAttribute::kCaretBounds:
       AddEvent(node, Event::CARET_BOUNDS_CHANGED);
       break;
@@ -1367,10 +1464,14 @@
       return "flowFromChanged";
     case AXEventGenerator::Event::FLOW_TO_CHANGED:
       return "flowToChanged";
+    case AXEventGenerator::Event::GRAMMAR_MARKER_CHANGED:
+      return "grammarMarkerChanged";
     case AXEventGenerator::Event::HASPOPUP_CHANGED:
       return "haspopupChanged";
     case AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
       return "hierarchicalLevelChanged";
+    case AXEventGenerator::Event::HIGHLIGHT_MARKER_CHANGED:
+      return "highlightMarkerChanged";
     case AXEventGenerator::Event::IGNORED_CHANGED:
       return "ignoredChanged";
     case AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED:
@@ -1451,6 +1552,8 @@
       return "setSizeChanged";
     case AXEventGenerator::Event::SORT_CHANGED:
       return "sortChanged";
+    case AXEventGenerator::Event::SPELLING_MARKER_CHANGED:
+      return "spellingMarkerChanged";
     case AXEventGenerator::Event::STATE_CHANGED:
       return "stateChanged";
     case AXEventGenerator::Event::SUBTREE_CREATED:
diff --git a/ui/accessibility/ax_event_generator.h b/ui/accessibility/ax_event_generator.h
index af9faf6..e4d05a3 100644
--- a/ui/accessibility/ax_event_generator.h
+++ b/ui/accessibility/ax_event_generator.h
@@ -66,8 +66,10 @@
     FOCUS_CHANGED,
     FLOW_FROM_CHANGED,
     FLOW_TO_CHANGED,
+    GRAMMAR_MARKER_CHANGED,
     HASPOPUP_CHANGED,
     HIERARCHICAL_LEVEL_CHANGED,
+    HIGHLIGHT_MARKER_CHANGED,
     IGNORED_CHANGED,
     IMAGE_ANNOTATION_CHANGED,
     INVALID_STATUS_CHANGED,
@@ -113,6 +115,7 @@
     SELECTED_VALUE_CHANGED,
     SET_SIZE_CHANGED,
     SORT_CHANGED,
+    SPELLING_MARKER_CHANGED,
     STATE_CHANGED,
     SUBTREE_CREATED,
     TEXT_ATTRIBUTE_CHANGED,
diff --git a/ui/accessibility/ax_event_generator_unittest.cc b/ui/accessibility/ax_event_generator_unittest.cc
index 89631cc..f6435c2c 100644
--- a/ui/accessibility/ax_event_generator_unittest.cc
+++ b/ui/accessibility/ax_event_generator_unittest.cc
@@ -1235,7 +1235,9 @@
           HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 8),
           HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 9),
           HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 10),
+          HasEventAtNode(AXEventGenerator::Event::SPELLING_MARKER_CHANGED, 10),
           HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 11),
+          HasEventAtNode(AXEventGenerator::Event::GRAMMAR_MARKER_CHANGED, 11),
           HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 12),
           HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 13),
           HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 14),
@@ -3171,4 +3173,438 @@
                   HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 3)));
 }
 
+// Tests that adding a spelling marker via kMarkerTypes fires both
+// TEXT_ATTRIBUTE_CHANGED and SPELLING_MARKER_CHANGED.
+TEST(AXEventGeneratorTest, SpellingMarkerAddedViaMarkerTypes) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(2);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].child_ids = {2};
+  initial_state.nodes[1].id = 2;
+  initial_state.nodes[1].AddState(ax::mojom::State::kRichlyEditable);
+
+  AXTree tree(initial_state);
+  AXEventGenerator event_generator(&tree);
+  ASSERT_THAT(event_generator, IsEmpty());
+
+  AXTreeUpdate update = initial_state;
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kSpelling)});
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kNone)});
+  ASSERT_TRUE(tree.Unserialize(update));
+
+  EXPECT_THAT(
+      event_generator,
+      UnorderedElementsAre(
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 2),
+          HasEventAtNode(AXEventGenerator::Event::SPELLING_MARKER_CHANGED, 2)));
+}
+
+// Tests that adding a grammar marker via kMarkerTypes fires both
+// TEXT_ATTRIBUTE_CHANGED and GRAMMAR_MARKER_CHANGED.
+TEST(AXEventGeneratorTest, GrammarMarkerAddedViaMarkerTypes) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(2);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].child_ids = {2};
+  initial_state.nodes[1].id = 2;
+  initial_state.nodes[1].AddState(ax::mojom::State::kRichlyEditable);
+
+  AXTree tree(initial_state);
+  AXEventGenerator event_generator(&tree);
+  ASSERT_THAT(event_generator, IsEmpty());
+
+  AXTreeUpdate update = initial_state;
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kGrammar)});
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kNone)});
+  ASSERT_TRUE(tree.Unserialize(update));
+
+  EXPECT_THAT(
+      event_generator,
+      UnorderedElementsAre(
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 2),
+          HasEventAtNode(AXEventGenerator::Event::GRAMMAR_MARKER_CHANGED, 2)));
+}
+
+// Tests that adding both spelling and grammar markers at the same time fires
+// TEXT_ATTRIBUTE_CHANGED, SPELLING_MARKER_CHANGED, and GRAMMAR_MARKER_CHANGED.
+TEST(AXEventGeneratorTest, SpellingAndGrammarMarkersAddedViaMarkerTypes) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(2);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].child_ids = {2};
+  initial_state.nodes[1].id = 2;
+  initial_state.nodes[1].AddState(ax::mojom::State::kRichlyEditable);
+
+  AXTree tree(initial_state);
+  AXEventGenerator event_generator(&tree);
+  ASSERT_THAT(event_generator, IsEmpty());
+
+  AXTreeUpdate update = initial_state;
+  // Two markers: one spelling, one grammar.
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kSpelling),
+       static_cast<int32_t>(ax::mojom::MarkerType::kGrammar)});
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kNone),
+       static_cast<int32_t>(ax::mojom::HighlightType::kNone)});
+  ASSERT_TRUE(tree.Unserialize(update));
+
+  EXPECT_THAT(
+      event_generator,
+      UnorderedElementsAre(
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 2),
+          HasEventAtNode(AXEventGenerator::Event::SPELLING_MARKER_CHANGED, 2),
+          HasEventAtNode(AXEventGenerator::Event::GRAMMAR_MARKER_CHANGED, 2)));
+}
+
+// Tests that removing markers fires only
+// TEXT_ATTRIBUTE_CHANGED and not specific marker events.
+TEST(AXEventGeneratorTest, MarkerTypesRemovedNoSpecificEvent) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(2);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].child_ids = {2};
+  initial_state.nodes[1].id = 2;
+  initial_state.nodes[1].AddState(ax::mojom::State::kRichlyEditable);
+  // Start with two markers.
+  initial_state.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kSpelling),
+       static_cast<int32_t>(ax::mojom::MarkerType::kGrammar)});
+  initial_state.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kNone),
+       static_cast<int32_t>(ax::mojom::HighlightType::kNone)});
+
+  AXTree tree(initial_state);
+  AXEventGenerator event_generator(&tree);
+  ASSERT_THAT(event_generator, IsEmpty());
+
+  AXTreeUpdate update = initial_state;
+  // Remove one marker (size decreases).
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kSpelling)});
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kNone)});
+  ASSERT_TRUE(tree.Unserialize(update));
+
+  // Only TEXT_ATTRIBUTE_CHANGED should fire, not SPELLING_MARKER_CHANGED or
+  // GRAMMAR_MARKER_CHANGED.
+  EXPECT_THAT(event_generator,
+              UnorderedElementsAre(HasEventAtNode(
+                  AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 2)));
+}
+
+// Tests that changing a marker type at an existing index (e.g., from
+// kTextMatch to kSpelling) fires the newly added marker event.
+TEST(AXEventGeneratorTest, MarkerTypeChangedAtExistingIndex) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(2);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].child_ids = {2};
+  initial_state.nodes[1].id = 2;
+  initial_state.nodes[1].AddState(ax::mojom::State::kRichlyEditable);
+  initial_state.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kTextMatch)});
+  initial_state.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kNone)});
+
+  AXTree tree(initial_state);
+  AXEventGenerator event_generator(&tree);
+  ASSERT_THAT(event_generator, IsEmpty());
+
+  AXTreeUpdate update = initial_state;
+  // Change marker from kTextMatch to kSpelling at the same index.
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kSpelling)});
+  ASSERT_TRUE(tree.Unserialize(update));
+
+  EXPECT_THAT(
+      event_generator,
+      UnorderedElementsAre(
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 2),
+          HasEventAtNode(AXEventGenerator::Event::SPELLING_MARKER_CHANGED, 2)));
+}
+
+// Tests that adding a highlight type of kSpellingError fires
+// SPELLING_MARKER_CHANGED via kHighlightTypes.
+TEST(AXEventGeneratorTest, HighlightTypeSpellingErrorAdded) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(2);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].child_ids = {2};
+  initial_state.nodes[1].id = 2;
+  initial_state.nodes[1].AddState(ax::mojom::State::kRichlyEditable);
+
+  AXTree tree(initial_state);
+  AXEventGenerator event_generator(&tree);
+  ASSERT_THAT(event_generator, IsEmpty());
+
+  AXTreeUpdate update = initial_state;
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kHighlight)});
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kSpellingError)});
+  ASSERT_TRUE(tree.Unserialize(update));
+
+  EXPECT_THAT(
+      event_generator,
+      UnorderedElementsAre(
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 2),
+          HasEventAtNode(AXEventGenerator::Event::SPELLING_MARKER_CHANGED, 2)));
+}
+
+// Tests that adding a highlight type of kGrammarError fires
+// GRAMMAR_MARKER_CHANGED via kHighlightTypes.
+TEST(AXEventGeneratorTest, HighlightTypeGrammarErrorAdded) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(2);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].child_ids = {2};
+  initial_state.nodes[1].id = 2;
+  initial_state.nodes[1].AddState(ax::mojom::State::kRichlyEditable);
+
+  AXTree tree(initial_state);
+  AXEventGenerator event_generator(&tree);
+  ASSERT_THAT(event_generator, IsEmpty());
+
+  AXTreeUpdate update = initial_state;
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kHighlight)});
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kGrammarError)});
+  ASSERT_TRUE(tree.Unserialize(update));
+
+  EXPECT_THAT(
+      event_generator,
+      UnorderedElementsAre(
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 2),
+          HasEventAtNode(AXEventGenerator::Event::GRAMMAR_MARKER_CHANGED, 2)));
+}
+
+// Tests that adding a highlight type of kHighlight fires
+// HIGHLIGHT_MARKER_CHANGED via kHighlightTypes.
+TEST(AXEventGeneratorTest, HighlightTypeHighlightAdded) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(2);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].child_ids = {2};
+  initial_state.nodes[1].id = 2;
+  initial_state.nodes[1].AddState(ax::mojom::State::kRichlyEditable);
+
+  AXTree tree(initial_state);
+  AXEventGenerator event_generator(&tree);
+  ASSERT_THAT(event_generator, IsEmpty());
+
+  AXTreeUpdate update = initial_state;
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kHighlight)});
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kHighlight)});
+  ASSERT_TRUE(tree.Unserialize(update));
+
+  EXPECT_THAT(
+      event_generator,
+      UnorderedElementsAre(
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 2),
+          HasEventAtNode(AXEventGenerator::Event::HIGHLIGHT_MARKER_CHANGED,
+                         2)));
+}
+
+// Tests that removing highlight types (old_value.size() > new_value.size())
+// fires only TEXT_ATTRIBUTE_CHANGED and not specific marker events.
+TEST(AXEventGeneratorTest, HighlightTypesRemovedNoSpecificEvent) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(2);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].child_ids = {2};
+  initial_state.nodes[1].id = 2;
+  initial_state.nodes[1].AddState(ax::mojom::State::kRichlyEditable);
+  initial_state.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kHighlight),
+       static_cast<int32_t>(ax::mojom::MarkerType::kHighlight)});
+  initial_state.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kSpellingError),
+       static_cast<int32_t>(ax::mojom::HighlightType::kGrammarError)});
+
+  AXTree tree(initial_state);
+  AXEventGenerator event_generator(&tree);
+  ASSERT_THAT(event_generator, IsEmpty());
+
+  AXTreeUpdate update = initial_state;
+  // Remove one highlight type.
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kHighlight)});
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kSpellingError)});
+  ASSERT_TRUE(tree.Unserialize(update));
+
+  EXPECT_THAT(event_generator,
+              UnorderedElementsAre(HasEventAtNode(
+                  AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 2)));
+}
+
+// Tests that changing a highlight type at an existing index fires the
+// appropriate specific marker event.
+TEST(AXEventGeneratorTest, HighlightTypeChangedAtExistingIndex) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(2);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].child_ids = {2};
+  initial_state.nodes[1].id = 2;
+  initial_state.nodes[1].AddState(ax::mojom::State::kRichlyEditable);
+  initial_state.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kHighlight)});
+  // Start with kHighlight.
+  initial_state.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kHighlight)});
+
+  AXTree tree(initial_state);
+  AXEventGenerator event_generator(&tree);
+  ASSERT_THAT(event_generator, IsEmpty());
+
+  AXTreeUpdate update = initial_state;
+  // Change from kHighlight to kSpellingError at the same index.
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kSpellingError)});
+  ASSERT_TRUE(tree.Unserialize(update));
+
+  EXPECT_THAT(
+      event_generator,
+      UnorderedElementsAre(
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 2),
+          HasEventAtNode(AXEventGenerator::Event::SPELLING_MARKER_CHANGED, 2)));
+}
+
+// Tests that all three highlight types can be added at once and fire
+// their respective events.
+TEST(AXEventGeneratorTest, MultipleHighlightTypesAdded) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(2);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].child_ids = {2};
+  initial_state.nodes[1].id = 2;
+  initial_state.nodes[1].AddState(ax::mojom::State::kRichlyEditable);
+
+  AXTree tree(initial_state);
+  AXEventGenerator event_generator(&tree);
+  ASSERT_THAT(event_generator, IsEmpty());
+
+  AXTreeUpdate update = initial_state;
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kHighlight),
+       static_cast<int32_t>(ax::mojom::MarkerType::kHighlight),
+       static_cast<int32_t>(ax::mojom::MarkerType::kHighlight)});
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kHighlightTypes,
+      {static_cast<int32_t>(ax::mojom::HighlightType::kSpellingError),
+       static_cast<int32_t>(ax::mojom::HighlightType::kGrammarError),
+       static_cast<int32_t>(ax::mojom::HighlightType::kHighlight)});
+  ASSERT_TRUE(tree.Unserialize(update));
+
+  EXPECT_THAT(
+      event_generator,
+      UnorderedElementsAre(
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 2),
+          HasEventAtNode(AXEventGenerator::Event::SPELLING_MARKER_CHANGED, 2),
+          HasEventAtNode(AXEventGenerator::Event::GRAMMAR_MARKER_CHANGED, 2),
+          HasEventAtNode(AXEventGenerator::Event::HIGHLIGHT_MARKER_CHANGED,
+                         2)));
+}
+
+// Tests that marker events are fired on the text field ancestor node when the
+// child node is not richly editable but has a text field ancestor.
+TEST(AXEventGeneratorTest, MarkerEventsOnTextFieldAncestor) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(2);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].role = ax::mojom::Role::kTextField;
+  initial_state.nodes[0].child_ids = {2};
+  initial_state.nodes[1].id = 2;
+  // Node 2 is not richly editable, but has a text field ancestor (node 1).
+
+  AXTree tree(initial_state);
+  AXEventGenerator event_generator(&tree);
+  ASSERT_THAT(event_generator, IsEmpty());
+
+  AXTreeUpdate update = initial_state;
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kSpelling)});
+  ASSERT_TRUE(tree.Unserialize(update));
+
+  // Events should be fired on the text field ancestor (node 1), not node 2.
+  EXPECT_THAT(
+      event_generator,
+      UnorderedElementsAre(
+          HasEventAtNode(AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED, 1),
+          HasEventAtNode(AXEventGenerator::Event::SPELLING_MARKER_CHANGED, 1)));
+}
+
+// Tests that marker events are not fired when node has no text field ancestor
+// and is not richly editable.
+TEST(AXEventGeneratorTest, MarkerEventsNoTargetNoEvent) {
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(2);
+  initial_state.nodes[0].id = 1;
+  initial_state.nodes[0].child_ids = {2};
+  initial_state.nodes[1].id = 2;
+  // Node 2 is neither richly editable nor has a text field ancestor.
+
+  AXTree tree(initial_state);
+  AXEventGenerator event_generator(&tree);
+  ASSERT_THAT(event_generator, IsEmpty());
+
+  AXTreeUpdate update = initial_state;
+  update.nodes[1].AddIntListAttribute(
+      ax::mojom::IntListAttribute::kMarkerTypes,
+      {static_cast<int32_t>(ax::mojom::MarkerType::kSpelling)});
+  ASSERT_TRUE(tree.Unserialize(update));
+
+  // No events should be fired since there's no valid target.
+  EXPECT_THAT(event_generator, IsEmpty());
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/platform/automation/automation_api_util.cc b/ui/accessibility/platform/automation/automation_api_util.cc
index 6883c0e4..58389b8 100644
--- a/ui/accessibility/platform/automation/automation_api_util.cc
+++ b/ui/accessibility/platform/automation/automation_api_util.cc
@@ -126,8 +126,10 @@
     case AXEventGenerator::Event::FOCUS_CHANGED:
     case AXEventGenerator::Event::FLOW_FROM_CHANGED:
     case AXEventGenerator::Event::FLOW_TO_CHANGED:
+    case AXEventGenerator::Event::GRAMMAR_MARKER_CHANGED:
     case AXEventGenerator::Event::HASPOPUP_CHANGED:
     case AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
+    case AXEventGenerator::Event::HIGHLIGHT_MARKER_CHANGED:
     case AXEventGenerator::Event::IGNORED_CHANGED:
     case AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED:
     case AXEventGenerator::Event::INVALID_STATUS_CHANGED:
@@ -164,6 +166,7 @@
     case AXEventGenerator::Event::TEXT_SELECTION_CHANGED:
     case AXEventGenerator::Event::SET_SIZE_CHANGED:
     case AXEventGenerator::Event::SORT_CHANGED:
+    case AXEventGenerator::Event::SPELLING_MARKER_CHANGED:
     case AXEventGenerator::Event::STATE_CHANGED:
     case AXEventGenerator::Event::SUBTREE_CREATED:
     case AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
diff --git a/ui/accessibility/platform/browser_accessibility_manager_auralinux.cc b/ui/accessibility/platform/browser_accessibility_manager_auralinux.cc
index 51efa59..adc3aed 100644
--- a/ui/accessibility/platform/browser_accessibility_manager_auralinux.cc
+++ b/ui/accessibility/platform/browser_accessibility_manager_auralinux.cc
@@ -378,8 +378,10 @@
     case AXEventGenerator::Event::FOCUS_CHANGED:
     case AXEventGenerator::Event::FLOW_FROM_CHANGED:
     case AXEventGenerator::Event::FLOW_TO_CHANGED:
+    case AXEventGenerator::Event::GRAMMAR_MARKER_CHANGED:
     case AXEventGenerator::Event::HASPOPUP_CHANGED:
     case AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
+    case AXEventGenerator::Event::HIGHLIGHT_MARKER_CHANGED:
     case AXEventGenerator::Event::IGNORED_CHANGED:
     case AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED:
     case AXEventGenerator::Event::KEY_SHORTCUTS_CHANGED:
@@ -406,6 +408,7 @@
     case AXEventGenerator::Event::SCROLL_HORIZONTAL_POSITION_CHANGED:
     case AXEventGenerator::Event::SCROLL_VERTICAL_POSITION_CHANGED:
     case AXEventGenerator::Event::SET_SIZE_CHANGED:
+    case AXEventGenerator::Event::SPELLING_MARKER_CHANGED:
     case AXEventGenerator::Event::STATE_CHANGED:
     case AXEventGenerator::Event::TEXT_SELECTION_CHANGED:
     case AXEventGenerator::Event::WIN_IACCESSIBLE_STATE_CHANGED:
diff --git a/ui/accessibility/platform/browser_accessibility_manager_mac.mm b/ui/accessibility/platform/browser_accessibility_manager_mac.mm
index 423fa6c..6c0b1c20 100644
--- a/ui/accessibility/platform/browser_accessibility_manager_mac.mm
+++ b/ui/accessibility/platform/browser_accessibility_manager_mac.mm
@@ -401,8 +401,10 @@
     case AXEventGenerator::Event::FOCUS_CHANGED:
     case AXEventGenerator::Event::FLOW_FROM_CHANGED:
     case AXEventGenerator::Event::FLOW_TO_CHANGED:
+    case AXEventGenerator::Event::GRAMMAR_MARKER_CHANGED:
     case AXEventGenerator::Event::HASPOPUP_CHANGED:
     case AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
+    case AXEventGenerator::Event::HIGHLIGHT_MARKER_CHANGED:
     case AXEventGenerator::Event::IGNORED_CHANGED:
     case AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED:
     case AXEventGenerator::Event::KEY_SHORTCUTS_CHANGED:
@@ -431,6 +433,7 @@
     case AXEventGenerator::Event::SELECTED_CHANGED:
     case AXEventGenerator::Event::SET_SIZE_CHANGED:
     case AXEventGenerator::Event::SORT_CHANGED:
+    case AXEventGenerator::Event::SPELLING_MARKER_CHANGED:
     case AXEventGenerator::Event::STATE_CHANGED:
     case AXEventGenerator::Event::SUBTREE_CREATED:
     case AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
diff --git a/ui/accessibility/platform/browser_accessibility_manager_win.cc b/ui/accessibility/platform/browser_accessibility_manager_win.cc
index 3591c2d..bc68262 100644
--- a/ui/accessibility/platform/browser_accessibility_manager_win.cc
+++ b/ui/accessibility/platform/browser_accessibility_manager_win.cc
@@ -602,6 +602,15 @@
     case AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
       FireWinAccessibilityEvent(IA2_EVENT_TEXT_ATTRIBUTE_CHANGED, wrapper);
       break;
+    case AXEventGenerator::Event::SPELLING_MARKER_CHANGED:
+      FireUiaChangesEvent(wrapper, AnnotationType_SpellingError);
+      break;
+    case AXEventGenerator::Event::GRAMMAR_MARKER_CHANGED:
+      FireUiaChangesEvent(wrapper, AnnotationType_GrammarError);
+      break;
+    case AXEventGenerator::Event::HIGHLIGHT_MARKER_CHANGED:
+      FireUiaChangesEvent(wrapper, AnnotationType_Highlighted);
+      break;
     case AXEventGenerator::Event::VALUE_IN_TEXT_FIELD_CHANGED:
       DCHECK(wrapper->IsTextField());
       FireWinAccessibilityEvent(EVENT_OBJECT_VALUECHANGE, wrapper);
@@ -863,6 +872,46 @@
   active_text_position_changed_func(provider, text_range.Get());
 }
 
+void BrowserAccessibilityManagerWin::FireUiaChangesEvent(
+    BrowserAccessibility* node,
+    int annotation_type_id) {
+  if (!AXPlatform::GetInstance().IsUiaProviderEnabled()) {
+    return;
+  }
+  if (!ShouldFireEventForNode(node)) {
+    return;
+  }
+  if (IsIgnoredChangedNode(node) || node->IsIgnored()) {
+    return;
+  }
+
+  // UiaRaiseChangesEvent is available since Windows 10 according to
+  // https://learn.microsoft.com/en-us/windows/win32/api/uiautomationcoreapi/nf-uiautomationcoreapi-uiaraisechangesevent#requirements.
+  // Resolve it at runtime to avoid failing to load on older versions.
+  using UiaRaiseChangesEventFunction =
+      HRESULT(WINAPI*)(IRawElementProviderSimple*, int, UiaChangeInfo*);
+  static const UiaRaiseChangesEventFunction raise_changes_event_func =
+      reinterpret_cast<UiaRaiseChangesEventFunction>(::GetProcAddress(
+          ::GetModuleHandle(L"uiautomationcore.dll"), "UiaRaiseChangesEvent"));
+  if (!raise_changes_event_func) {
+    return;
+  }
+
+  auto* provider = ToBrowserAccessibilityWin(node)->GetCOM();
+  if (!provider->HasEventListenerForEvent(UIA_ChangesEventId)) {
+    return;
+  }
+
+  WinAccessibilityAPIUsageScopedUIAEventsNotifier scoped_events_notifier;
+
+  UiaChangeInfo change = {};
+  change.uiaId = annotation_type_id;
+  // TODO(crbug.com/479561828): Set the payload field of UiaChangeInfo with
+  // relevant information of the change, such as the marker's text content when
+  // there's a spelling or grammar error.
+  raise_changes_event_func(provider, 1, &change);
+}
+
 bool BrowserAccessibilityManagerWin::CanFireEvents() const {
   if (!BrowserAccessibilityManager::CanFireEvents()) {
     return false;
diff --git a/ui/accessibility/platform/browser_accessibility_manager_win.h b/ui/accessibility/platform/browser_accessibility_manager_win.h
index 5abe07d..5f7e99b 100644
--- a/ui/accessibility/platform/browser_accessibility_manager_win.h
+++ b/ui/accessibility/platform/browser_accessibility_manager_win.h
@@ -82,6 +82,7 @@
                                    BrowserAccessibility* node);
   void FireUiaStructureChangedEvent(StructureChangeType change_type,
                                     BrowserAccessibility* node);
+  void FireUiaChangesEvent(BrowserAccessibility* node, int annotation_type_id);
 
   gfx::Rect GetViewBoundsInScreenCoordinates() const override;
 
diff --git a/ui/accessibility/platform/inspect/ax_event_recorder_win_uia.cc b/ui/accessibility/platform/inspect/ax_event_recorder_win_uia.cc
index ac16da29f..f383c5b 100644
--- a/ui/accessibility/platform/inspect/ax_event_recorder_win_uia.cc
+++ b/ui/accessibility/platform/inspect/ax_event_recorder_win_uia.cc
@@ -10,6 +10,8 @@
 #include <numeric>
 #include <utility>
 
+#include "base/compiler_specific.h"
+#include "base/containers/span.h"
 #include "base/logging.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -134,9 +136,10 @@
   base::win::ScopedCOMInitializer com_init{
       base::win::ScopedCOMInitializer::kMTA};
 
-  // Create an instance of the CUIAutomation class.
-  CoCreateInstance(CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER,
-                   IID_IUIAutomation, &uia_);
+  // Create an instance of the CUIAutomation8 class, which natively supports the
+  // IUIAutomation4 interface needed for AddChangesEventHandler.
+  CoCreateInstance(CLSID_CUIAutomation8, nullptr, CLSCTX_INPROC_SERVER,
+                   IID_PPV_ARGS(&uia_));
   CHECK(uia_.Get());
 
   // Register the custom event to mark the end of the test.
@@ -182,19 +185,32 @@
                                         cache_request_.Get(),
                                         uia_event_handler_.Get());
 
-  // Subscribe to all automation events (except structure-change events and
-  // live-region events, which are handled elsewhere).
+  // Subscribe to all automation events (except structure-change events,
+  // live-region events, and changes events, which are handled elsewhere).
   static const EVENTID kMinEvent = UIA_ToolTipOpenedEventId;
   static const EVENTID kMaxEvent = UIA_ActiveTextPositionChangedEventId;
   for (EVENTID event_id = kMinEvent; event_id <= kMaxEvent; ++event_id) {
     if (event_id != UIA_StructureChangedEventId &&
-        event_id != UIA_LiveRegionChangedEventId) {
+        event_id != UIA_LiveRegionChangedEventId &&
+        event_id != UIA_ChangesEventId) {
       uia_->AddAutomationEventHandler(
           event_id, root_.Get(), TreeScope::TreeScope_Subtree,
           cache_request_.Get(), uia_event_handler_.Get());
     }
   }
 
+  // Subscribe to changes events (e.g., annotation type changes for spelling,
+  // grammar, and highlights).
+  {
+    int change_types[] = {AnnotationType_SpellingError,
+                          AnnotationType_GrammarError,
+                          AnnotationType_Highlighted};
+    uia_->AddChangesEventHandler(root_.Get(), TreeScope::TreeScope_Subtree,
+                                 change_types, std::size(change_types),
+                                 cache_request_.Get(),
+                                 uia_event_handler_.Get());
+  }
+
   // Subscribe to live-region change events.  This must be the last event we
   // subscribe to, because |AXFragmentRootWin| will fire events when advised of
   // the subscription, and this can hang the test-process (on Windows 19H1+) if
@@ -404,6 +420,45 @@
   return S_OK;
 }
 
+IFACEMETHODIMP
+AXEventRecorderWinUia::Thread::EventHandler::HandleChangesEvent(
+    IUIAutomationElement* sender,
+    UiaChangeInfo* uia_changes,
+    int changes_count) {
+  if (!owner_ || !IsCallerFromAllowedModule(RETURN_ADDRESS())) {
+    return S_OK;
+  }
+
+  // SAFETY: `uia_changes` points to an array of `changes_count` elements
+  // provided by the UIA framework.
+  auto changes = UNSAFE_BUFFERS(base::span<UiaChangeInfo>(
+      uia_changes, static_cast<size_t>(changes_count)));
+  for (const auto& change : changes) {
+    std::string change_type_str;
+    switch (change.uiaId) {
+      case AnnotationType_SpellingError:
+        change_type_str = "AnnotationType_SpellingError";
+        break;
+      case AnnotationType_GrammarError:
+        change_type_str = "AnnotationType_GrammarError";
+        break;
+      case AnnotationType_Highlighted:
+        change_type_str = "AnnotationType_Highlighted";
+        break;
+      default:
+        change_type_str = base::StringPrintf("ChangeId_%d", change.uiaId);
+        break;
+    }
+
+    std::string log =
+        base::StringPrintf("Changes/%s %s", change_type_str.c_str(),
+                           GetSenderInfo(sender).c_str());
+    owner_->OnEvent(log);
+  }
+
+  return S_OK;
+}
+
 // Due to a bug in Windows (fixed in Windows 10 19H1, but found broken in 20H2),
 // events are raised exactly twice for any in-proc off-thread event listeners.
 // To avoid this, in UIA API methods we can pass the RETURN_ADDRESS() to this
diff --git a/ui/accessibility/platform/inspect/ax_event_recorder_win_uia.h b/ui/accessibility/platform/inspect/ax_event_recorder_win_uia.h
index 9523576..e31f40a 100644
--- a/ui/accessibility/platform/inspect/ax_event_recorder_win_uia.h
+++ b/ui/accessibility/platform/inspect/ax_event_recorder_win_uia.h
@@ -67,7 +67,7 @@
     HWND hwnd_ = NULL;
     EVENTID shutdown_sentinel_ = 0;
 
-    Microsoft::WRL::ComPtr<IUIAutomation> uia_;
+    Microsoft::WRL::ComPtr<IUIAutomation4> uia_;
     Microsoft::WRL::ComPtr<IUIAutomationElement> root_;
     Microsoft::WRL::ComPtr<IUIAutomationCacheRequest> cache_request_;
 
@@ -84,7 +84,8 @@
                          public IUIAutomationFocusChangedEventHandler,
                          public IUIAutomationPropertyChangedEventHandler,
                          public IUIAutomationStructureChangedEventHandler,
-                         public IUIAutomationEventHandler {
+                         public IUIAutomationEventHandler,
+                         public IUIAutomationChangesEventHandler {
      public:
       EventHandler();
 
@@ -102,6 +103,7 @@
       COM_INTERFACE_ENTRY(IUIAutomationPropertyChangedEventHandler)
       COM_INTERFACE_ENTRY(IUIAutomationStructureChangedEventHandler)
       COM_INTERFACE_ENTRY(IUIAutomationEventHandler)
+      COM_INTERFACE_ENTRY(IUIAutomationChangesEventHandler)
       END_COM_MAP()
 
       // IUIAutomationFocusChangedEventHandler interface.
@@ -123,6 +125,11 @@
       IFACEMETHODIMP HandleAutomationEvent(IUIAutomationElement* sender,
                                            EVENTID event_id) override;
 
+      // IUIAutomationChangesEventHandler interface.
+      IFACEMETHODIMP HandleChangesEvent(IUIAutomationElement* sender,
+                                        UiaChangeInfo* uia_changes,
+                                        int changes_count) override;
+
       // Points to the event recorder to receive notifications.
       raw_ptr<AXEventRecorderWinUia::Thread> owner_ = nullptr;
 
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn
index d39348ce..359208c 100644
--- a/ui/android/BUILD.gn
+++ b/ui/android/BUILD.gn
@@ -30,6 +30,8 @@
 component("android") {
   output_name = "ui_android"
   sources = [
+    "accelerator_manager_android.cc",
+    "accelerator_manager_android.h",
     "animation_utils.h",
     "browser_controls_offset_tag_constraints.h",
     "browser_controls_offset_tag_definitions.cc",
@@ -160,6 +162,7 @@
     "java/src/org/chromium/ui/ModalDialogWrapper.java",
     "java/src/org/chromium/ui/OffsetTagConstraints.java",
     "java/src/org/chromium/ui/OverscrollRefreshHandler.java",
+    "java/src/org/chromium/ui/base/AcceleratorManager.java",
     "java/src/org/chromium/ui/base/BytesFormatting.java",
     "java/src/org/chromium/ui/base/EventForwarder.java",
     "java/src/org/chromium/ui/base/LocalizationUtils.java",
@@ -394,6 +397,7 @@
     "java/src/org/chromium/ui/animation/RunOnNextLayoutDelegate.java",
     "java/src/org/chromium/ui/animation/TranslationAnimatorFactory.java",
     "java/src/org/chromium/ui/animation/ViewCurvedMotionAnimatorFactory.java",
+    "java/src/org/chromium/ui/base/AcceleratorManager.java",
     "java/src/org/chromium/ui/base/ActivityIntentRequestTrackerDelegate.java",
     "java/src/org/chromium/ui/base/ActivityKeyboardVisibilityDelegate.java",
     "java/src/org/chromium/ui/base/ActivityResultTracker.java",
diff --git a/ui/android/accelerator_manager_android.cc b/ui/android/accelerator_manager_android.cc
new file mode 100644
index 0000000..f06d6722
--- /dev/null
+++ b/ui/android/accelerator_manager_android.cc
@@ -0,0 +1,82 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/android/accelerator_manager_android.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "ui/android/window_android.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/base/accelerators/accelerator_manager.h"
+#include "ui/events/android/key_event_android.h"
+#include "ui/events/event.h"
+
+// Must come after all headers that specialize FromJniType() / ToJniType().
+#include "ui/android/ui_android_jni_headers/AcceleratorManager_jni.h"
+
+namespace ui {
+
+using base::android::AttachCurrentThread;
+using base::android::ScopedJavaLocalRef;
+
+AcceleratorManagerAndroid* AcceleratorManagerAndroid::FromWindow(
+    WindowAndroid& window) {
+  JNIEnv* env = AttachCurrentThread();
+  return reinterpret_cast<AcceleratorManagerAndroid*>(
+      Java_AcceleratorManager_getNativePointerFromWindow(
+          env, window.GetJavaObject()));
+}
+
+AcceleratorManagerAndroid::AcceleratorManagerAndroid(
+    base::android::ScopedJavaGlobalRef<jobject> obj)
+    : java_ref_(std::move(obj)) {}
+
+AcceleratorManagerAndroid::~AcceleratorManagerAndroid() = default;
+
+void AcceleratorManagerAndroid::RegisterAccelerator(
+    const Accelerator& accelerator,
+    AcceleratorManager::HandlerPriority priority,
+    AcceleratorTarget* target) {
+  bool first = accelerator_manager_.IsEmpty();
+  accelerator_manager_.RegisterAccelerator(accelerator, priority, target);
+  if (first) {
+    auto* env = AttachCurrentThread();
+    Java_AcceleratorManager_acceleratorsAreRegistered(env, java_ref_, true);
+  }
+}
+
+void AcceleratorManagerAndroid::UnregisterAccelerator(
+    const Accelerator& accelerator,
+    AcceleratorTarget* target) {
+  accelerator_manager_.Unregister(accelerator, target);
+  if (accelerator_manager_.IsEmpty()) {
+    auto* env = AttachCurrentThread();
+    Java_AcceleratorManager_acceleratorsAreRegistered(env, java_ref_, false);
+  }
+}
+
+void AcceleratorManagerAndroid::Destroy(JNIEnv* env) {
+  delete this;
+}
+
+bool AcceleratorManagerAndroid::ProcessKeyEvent(
+    JNIEnv* env,
+    const base::android::JavaRef<jobject>& j_key_event) {
+  KeyEventAndroid key_event_android(j_key_event);
+  ui::PlatformEvent native_event(key_event_android);
+  ui::KeyEvent key_event(native_event);
+  ui::Accelerator accelerator(key_event);
+  return accelerator_manager_.Process(accelerator);
+}
+
+int64_t JNI_AcceleratorManager_Init(
+    JNIEnv* env,
+    const base::android::JavaRef<jobject>& obj) {
+  return reinterpret_cast<int64_t>(new AcceleratorManagerAndroid(
+      base::android::ScopedJavaGlobalRef<jobject>(env, obj)));
+}
+
+}  // namespace ui
+
+DEFINE_JNI(AcceleratorManager)
diff --git a/ui/android/accelerator_manager_android.h b/ui/android/accelerator_manager_android.h
new file mode 100644
index 0000000..445868a4
--- /dev/null
+++ b/ui/android/accelerator_manager_android.h
@@ -0,0 +1,55 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ANDROID_ACCELERATOR_MANAGER_ANDROID_H_
+#define UI_ANDROID_ACCELERATOR_MANAGER_ANDROID_H_
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+#include "ui/android/ui_android_export.h"
+#include "ui/base/accelerators/accelerator_manager.h"
+
+namespace ui {
+
+class WindowAndroid;
+
+// Native bridge for AcceleratorManager.java.
+class UI_ANDROID_EXPORT AcceleratorManagerAndroid {
+ public:
+  // Returns the AcceleratorManagerAndroid for the given WindowAndroid. Returns
+  // nullptr if it doesn't exist.
+  static AcceleratorManagerAndroid* FromWindow(WindowAndroid& window);
+
+  explicit AcceleratorManagerAndroid(
+      base::android::ScopedJavaGlobalRef<jobject> obj);
+
+  AcceleratorManagerAndroid(const AcceleratorManagerAndroid&) = delete;
+  AcceleratorManagerAndroid& operator=(const AcceleratorManagerAndroid&) =
+      delete;
+
+  ~AcceleratorManagerAndroid();
+
+  void RegisterAccelerator(const Accelerator& accelerator,
+                           AcceleratorManager::HandlerPriority priority,
+                           AcceleratorTarget* target);
+
+  void UnregisterAccelerator(const Accelerator& accelerator,
+                             AcceleratorTarget* target);
+
+  // Functions to be called by JNI only.
+
+  bool ProcessKeyEvent(JNIEnv* env,
+                       const base::android::JavaRef<jobject>& j_key_event);
+
+  void Destroy(JNIEnv* env);
+
+ private:
+  base::android::ScopedJavaGlobalRef<jobject> java_ref_;
+  AcceleratorManager accelerator_manager_;
+};
+
+}  // namespace ui
+
+#endif  // UI_ANDROID_ACCELERATOR_MANAGER_ANDROID_H_
diff --git a/ui/android/event_forwarder.cc b/ui/android/event_forwarder.cc
index 7c3c937..021804a 100644
--- a/ui/android/event_forwarder.cc
+++ b/ui/android/event_forwarder.cc
@@ -421,12 +421,14 @@
   observers_.RemoveObserver(observer);
 }
 
-float EventForwarder::GetCurrentTouchSequenceYOffset() {
+gfx::PointF EventForwarder::GetCurrentTouchSequenceOffset() {
   CHECK(!java_obj_.is_uninitialized());
   JNIEnv* env = jni_zero::AttachCurrentThread();
   auto java_obj = java_obj_.get(env);
   DCHECK(!java_obj.is_null());
-  return Java_EventForwarder_getWebContentsOffsetYInWindow(env, java_obj);
+  return gfx::PointF(
+      Java_EventForwarder_getWebContentsOffsetXInWindow(env, java_obj),
+      Java_EventForwarder_getWebContentsOffsetYInWindow(env, java_obj));
 }
 
 }  // namespace ui
diff --git a/ui/android/event_forwarder.h b/ui/android/event_forwarder.h
index 67337dd..7a571c2 100644
--- a/ui/android/event_forwarder.h
+++ b/ui/android/event_forwarder.h
@@ -10,6 +10,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/observer_list.h"
 #include "ui/android/ui_android_export.h"
+#include "ui/gfx/geometry/point_f.h"
 
 namespace ui {
 
@@ -121,7 +122,7 @@
 
   void RemoveObserver(Observer* observer);
 
-  float GetCurrentTouchSequenceYOffset();
+  gfx::PointF GetCurrentTouchSequenceOffset();
 
  private:
   friend class ViewAndroid;
diff --git a/ui/android/java/src/org/chromium/ui/base/AcceleratorManager.java b/ui/android/java/src/org/chromium/ui/base/AcceleratorManager.java
new file mode 100644
index 0000000..b58a83c
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/base/AcceleratorManager.java
@@ -0,0 +1,104 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.ui.base;
+
+import android.view.KeyEvent;
+
+import org.jni_zero.CalledByNative;
+import org.jni_zero.JNINamespace;
+import org.jni_zero.NativeMethods;
+
+import org.chromium.base.UnownedUserDataKey;
+import org.chromium.base.lifetime.LifetimeAssert;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.build.annotations.Nullable;
+
+/** Creates and owns a native ui::AcceleratorManager. */
+@JNINamespace("ui")
+@NullMarked
+public class AcceleratorManager {
+    private static final UnownedUserDataKey<AcceleratorManager> KEY = new UnownedUserDataKey<>();
+    private final @Nullable LifetimeAssert mLifetimeAssert;
+    // Note: the native side is not created until it's first accessed in
+    // getNativePointerFromWindow().
+    private long mNativeAcceleratorManagerAndroid;
+    // False while no accelerators are registered. Accelerators can only be registered by native,
+    // so if this is true, we know native is initialized.
+    private boolean mAcceleratorsAreRegistered;
+
+    /** Retrieve the AcceleratorManager from the WindowAndroid, creating it if it doesn't exist. */
+    public static AcceleratorManager getOrCreate(WindowAndroid window) {
+        AcceleratorManager manager = from(window);
+        if (manager == null) {
+            manager = new AcceleratorManager(window);
+        }
+        return manager;
+    }
+
+    public void destroy() {
+        LifetimeAssert.destroy(mLifetimeAssert);
+        if (mNativeAcceleratorManagerAndroid != 0) {
+            AcceleratorManagerJni.get().destroy(mNativeAcceleratorManagerAndroid);
+            mNativeAcceleratorManagerAndroid = 0;
+            mAcceleratorsAreRegistered = false;
+        }
+    }
+
+    private AcceleratorManager(WindowAndroid window) {
+        mLifetimeAssert = LifetimeAssert.create(this);
+        KEY.attachToHost(window.getUnownedUserDataHost(), this);
+    }
+
+    /**
+     * Process a key event.
+     *
+     * @param event The key event to process.
+     * @return True if the event was handled.
+     */
+    public boolean processKeyEvent(KeyEvent event) {
+        return mNativeAcceleratorManagerAndroid != 0
+                && mAcceleratorsAreRegistered
+                && AcceleratorManagerJni.get()
+                        .processKeyEvent(mNativeAcceleratorManagerAndroid, event);
+    }
+
+    /** Retrieve the AcceleratorManager from the WindowAndroid, if it exists. */
+    private static @Nullable AcceleratorManager from(WindowAndroid window) {
+        return KEY.retrieveDataFromHost(window.getUnownedUserDataHost());
+    }
+
+    @CalledByNative
+    private static long getNativePointerFromWindow(WindowAndroid window) {
+        AcceleratorManager manager = from(window);
+        if (manager == null) {
+            return 0;
+        }
+        return manager.getOrCreateNativePointer();
+    }
+
+    @CalledByNative
+    private long getOrCreateNativePointer() {
+        if (mNativeAcceleratorManagerAndroid == 0) {
+            mNativeAcceleratorManagerAndroid = AcceleratorManagerJni.get().init(this);
+        }
+        return mNativeAcceleratorManagerAndroid;
+    }
+
+    // Notifies java whether accelerators are present, so that we can skip the JNI call for key
+    // events if there are no accelerators present.
+    @CalledByNative
+    private void acceleratorsAreRegistered(boolean areRegistered) {
+        mAcceleratorsAreRegistered = areRegistered;
+    }
+
+    @NativeMethods
+    interface Natives {
+        long init(AcceleratorManager caller);
+
+        void destroy(long nativeAcceleratorManagerAndroid);
+
+        boolean processKeyEvent(long nativeAcceleratorManagerAndroid, KeyEvent event);
+    }
+}
diff --git a/ui/android/java/src/org/chromium/ui/base/Clipboard.java b/ui/android/java/src/org/chromium/ui/base/Clipboard.java
index 64afbcd..b9a6483 100644
--- a/ui/android/java/src/org/chromium/ui/base/Clipboard.java
+++ b/ui/android/java/src/org/chromium/ui/base/Clipboard.java
@@ -253,36 +253,36 @@
     }
 
     /**
-     * Emulates the behavior of the now-deprecated
-     * {@link android.text.ClipboardManager#setText(CharSequence)}, setting the
-     * clipboard's current primary clip to a plain-text clip that consists of
-     * the specified string.
-     * @param text  will become the content of the clipboard's primary clip.
+     * Emulates the behavior of the now-deprecated {@link
+     * android.text.ClipboardManager#setText(CharSequence)}, setting the clipboard's current primary
+     * clip to a plain-text clip that consists of the specified string.
+     *
+     * @param text will become the content of the clipboard's primary clip.
      */
     @CalledByNative
     public void setText(final String text) {
-        Log.w(TAG, "setText is a no-op because Clipboard service isn't available");
+        Log.w(TAG, "Clipboard service isn't available");
     }
 
     /**
      * Writes text to the clipboard.
      *
      * @param label the label for the clip data.
-     * @param text  will become the content of the clipboard's primary clip.
+     * @param text will become the content of the clipboard's primary clip.
      */
     public void setText(final String label, final String text) {
-        Log.w(TAG, "setText is a no-op because Clipboard service isn't available");
+        Log.w(TAG, "Clipboard service isn't available");
     }
 
     /**
      * Writes text to the clipboard.
      *
      * @param label the label for the clip data.
-     * @param text  will become the content of the clipboard's primary clip.
+     * @param text will become the content of the clipboard's primary clip.
      * @param notifyOnSuccess whether show a notification, e.g. a toast, to the user when success.
      */
     public void setText(final String label, final String text, boolean notifyOnSuccess) {
-        Log.w(TAG, "setText is a no-op because Clipboard service isn't available");
+        Log.w(TAG, "Clipboard service isn't available");
     }
 
     /**
@@ -294,16 +294,17 @@
     @CalledByNative
     @VisibleForTesting
     void setHTMLText(final String html, final String text) {
-        Log.w(TAG, "setHTMLText is a no-op because Clipboard service isn't available");
+        Log.w(TAG, "Clipboard service isn't available");
     }
 
     /**
      * Writes password to the clipboard, and set the Clipdata is sensitive.
-     * @param password  will become the content of the clipboard's primary clip.
+     *
+     * @param password will become the content of the clipboard's primary clip.
      */
     @CalledByNative
     public void setPassword(final String password) {
-        Log.w(TAG, "setPassword is a no-op because Clipboard service isn't available");
+        Log.w(TAG, "Clipboard service isn't available");
     }
 
     /**
@@ -313,7 +314,7 @@
      * @param uri The {@link Uri} will become the content of the clipboard's primary clip.
      */
     public void setImageUri(final Uri uri) {
-        Log.w(TAG, "setImageUri is a no-op because Clipboard service isn't available");
+        Log.w(TAG, "Clipboard service isn't available");
     }
 
     /**
@@ -325,18 +326,30 @@
      * @param notifyOnSuccess Whether show a notification when success.
      */
     public void setImageUri(final Uri uri, boolean notifyOnSuccess) {
-        Log.w(TAG, "setImageUriAndNotify is a no-op because Clipboard service isn't available");
+        Log.w(TAG, "Clipboard service isn't available");
     }
 
     /**
      * Setting the clipboard's current primary clip to an image.
+     *
+     * @param uri The {@link Uri} will become the content of the clipboard's primary clip.
+     * @param clipData The ClipData object to use.
+     * @param notifyOnSuccess Whether show a notification when success.
+     */
+    public void setImageUri(Uri uri, ClipData clipData, boolean notifyOnSuccess) {
+        Log.w(TAG, "Clipboard service isn't available");
+    }
+
+    /**
+     * Setting the clipboard's current primary clip to an image.
+     *
      * @param imageData The image data to be shared in |extension| format.
      * @param extension Image file extension which |imageData| encoded to.
      */
     @CalledByNative
     @VisibleForTesting
     public void setImage(final byte[] imageData, final String extension) {
-        Log.w(TAG, "setImage is a no-op because Clipboard service isn't available");
+        Log.w(TAG, "Clipboard service isn't available");
     }
 
     /**
@@ -346,7 +359,7 @@
      */
     @CalledByNative
     public void setFilenames(final String[] uriList) {
-        Log.w(TAG, "setFilenames is a no-op because Clipboard service isn't available");
+        Log.w(TAG, "Clipboard service isn't available");
     }
 
     /** Clears the Clipboard Primary clip. */
@@ -360,10 +373,11 @@
 
     /**
      * Set {@link ImageFileProvider} for sharing image.
+     *
      * @param imageFileProvider The implementation of {@link ImageFileProvider}.
      */
     public void setImageFileProvider(ImageFileProvider imageFileProvider) {
-        Log.w(TAG, "setImageFileProvider is a no-op because Clipboard service isn't available");
+        Log.w(TAG, "Clipboard service isn't available");
     }
 
     /**
diff --git a/ui/android/java/src/org/chromium/ui/base/ClipboardImpl.java b/ui/android/java/src/org/chromium/ui/base/ClipboardImpl.java
index 39eb4f7..b1b14de 100644
--- a/ui/android/java/src/org/chromium/ui/base/ClipboardImpl.java
+++ b/ui/android/java/src/org/chromium/ui/base/ClipboardImpl.java
@@ -448,31 +448,36 @@
 
             @Override
             protected void onPostExecute(@Nullable ClipData clipData) {
-                if (setPrimaryClipNoException(clipData) && notifyOnSuccess) {
-                    showToastIfNeeded(R.string.image_copied);
-                }
-
-                // Storing timestamp is for avoiding accessing the system clipboard data, which may
-                // cause the clipboard access notification to show up, when we try to clean up the
-                // image file. There is a small chance that the clipboard image is updated between
-                // |setPrimaryClipNoException| and |getImageTimestamp|, and we will get a wrong
-                // timestamp. But it is okay since the timestamp is for deciding if the image file
-                // need to be deleted. If the timestamp is wrong here, we just keep the image file a
-                // little longer than expected.
-                long imageTimestamp = getImageTimestamp();
-
-                if (mImageFileProvider == null) {
-                    mPendingCopiedImageMetadata =
-                            new ImageFileProvider.ClipboardFileMetadata(uri, imageTimestamp);
-                } else {
-                    mImageFileProvider.storeLastCopiedImageMetadata(
-                            new ImageFileProvider.ClipboardFileMetadata(uri, imageTimestamp));
-                }
+                setImageUri(uri, clipData, notifyOnSuccess);
             }
         }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
     @Override
+    public void setImageUri(Uri uri, ClipData clipData, boolean notifyOnSuccess) {
+        if (setPrimaryClipNoException(clipData) && notifyOnSuccess) {
+            showToastIfNeeded(R.string.image_copied);
+        }
+
+        // Storing timestamp is for avoiding accessing the system clipboard data, which may
+        // cause the clipboard access notification to show up, when we try to clean up the
+        // image file. There is a small chance that the clipboard image is updated between
+        // |setPrimaryClipNoException| and |getImageTimestamp|, and we will get a wrong
+        // timestamp. But it is okay since the timestamp is for deciding if the image file
+        // need to be deleted. If the timestamp is wrong here, we just keep the image file a
+        // little longer than expected.
+        long imageTimestamp = getImageTimestamp();
+
+        if (mImageFileProvider == null) {
+            mPendingCopiedImageMetadata =
+                    new ImageFileProvider.ClipboardFileMetadata(uri, imageTimestamp);
+        } else {
+            mImageFileProvider.storeLastCopiedImageMetadata(
+                    new ImageFileProvider.ClipboardFileMetadata(uri, imageTimestamp));
+        }
+    }
+
+    @Override
     public void setImage(final byte[] imageData, final String extension) {
         if (mImageFileProvider == null) {
             // Since |mImageFileProvider| is set on very early on during process init, and if
diff --git a/ui/android/java/src/org/chromium/ui/base/EventForwarder.java b/ui/android/java/src/org/chromium/ui/base/EventForwarder.java
index 5f0e3ff..32f4d30 100644
--- a/ui/android/java/src/org/chromium/ui/base/EventForwarder.java
+++ b/ui/android/java/src/org/chromium/ui/base/EventForwarder.java
@@ -268,6 +268,11 @@
     }
 
     @CalledByNative
+    private float getWebContentsOffsetXInWindow() {
+        return mCurrentTouchOffsetX;
+    }
+
+    @CalledByNative
     private float getWebContentsOffsetYInWindow() {
         return mCurrentTouchOffsetY;
     }
diff --git a/ui/base/accelerators/accelerator_manager.h b/ui/base/accelerators/accelerator_manager.h
index 5d6fd3b..647d170 100644
--- a/ui/base/accelerators/accelerator_manager.h
+++ b/ui/base/accelerators/accelerator_manager.h
@@ -86,6 +86,9 @@
   // Whether the given |accelerator| has a priority handler associated with it.
   bool HasPriorityHandler(const Accelerator& accelerator) const;
 
+  // Returns true if there are no accelerators registered.
+  bool IsEmpty() const { return accelerators_.empty(); }
+
 #if BUILDFLAG(IS_CHROMEOS)
   void SetUsePositionalLookup(bool use_positional_lookup) {
     DCHECK(::features::IsImprovedKeyboardShortcutsEnabled());
diff --git a/ui/color/color_variant.cc b/ui/color/color_variant.cc
index 8d9f52f..8be1eed 100644
--- a/ui/color/color_variant.cc
+++ b/ui/color/color_variant.cc
@@ -24,7 +24,7 @@
 
 ColorVariant::~ColorVariant() = default;
 
-bool ColorVariant::IsSemantic() const {
+bool ColorVariant::IsLogical() const {
   return !!GetColorId();
 }
 
diff --git a/ui/color/color_variant.h b/ui/color/color_variant.h
index 9f9111b4..6f7372e 100644
--- a/ui/color/color_variant.h
+++ b/ui/color/color_variant.h
@@ -51,11 +51,11 @@
   bool operator==(const SkColor& other) const { return GetSkColor() == other; }
   bool operator==(const ColorId& other) const { return GetColorId() == other; }
 
-  // Returns true if this ColorVariant currently holds a semantic color
+  // Returns true if this ColorVariant currently holds a logical color
   // reference (i.e., a ui::ColorId) rather than a physical color value
   // (SkColor). Semantic colors represent theme-based colors that require
   // resolution using a ui::ColorProvider via ResolveToSkColor().
-  bool IsSemantic() const;
+  bool IsLogical() const;
 
   // Returns true if this ColorVariant currently holds a physical color
   // reference (i.e., a SkColor)
diff --git a/ui/events/android/motion_event_android_factory.cc b/ui/events/android/motion_event_android_factory.cc
index 78144926..975173c 100644
--- a/ui/events/android/motion_event_android_factory.cc
+++ b/ui/events/android/motion_event_android_factory.cc
@@ -84,7 +84,7 @@
 std::unique_ptr<MotionEventAndroid> MotionEventAndroidFactory::CreateFromNative(
     base::android::ScopedInputEvent input_event,
     float pix_to_dip,
-    float y_offset_pix,
+    gfx::PointF offset,
     std::optional<MotionEventAndroid::EventTimes> event_times) {
   const AInputEvent* event = input_event.a_input_event();
 
@@ -120,8 +120,8 @@
   const std::unique_ptr<ui::MotionEventAndroid::Pointer> pointer0 =
       std::make_unique<ui::MotionEventAndroid::Pointer>(
           /*id=*/AMotionEvent_getPointerId(event, 0),
-          /*pos_x_pixels=*/AMotionEvent_getX(event, 0),
-          /*pos_y_pixels=*/AMotionEvent_getY(event, 0) + y_offset_pix,
+          /*pos_x_pixels=*/AMotionEvent_getX(event, 0) + offset.x(),
+          /*pos_y_pixels=*/AMotionEvent_getY(event, 0) + offset.y(),
           /*touch_major_pixels=*/AMotionEvent_getTouchMajor(event, 0),
           /*touch_minor_pixels=*/AMotionEvent_getTouchMinor(event, 0),
           /*pressure=*/AMotionEvent_getPressure(event, 0),
@@ -134,8 +134,8 @@
   if (pointer_count > 1) {
     pointer1 = std::make_unique<ui::MotionEventAndroid::Pointer>(
         /*id=*/AMotionEvent_getPointerId(event, 1),
-        /*pos_x_pixels=*/AMotionEvent_getX(event, 1),
-        /*pos_y_pixels=*/AMotionEvent_getY(event, 1) + y_offset_pix,
+        /*pos_x_pixels=*/AMotionEvent_getX(event, 1) + offset.x(),
+        /*pos_y_pixels=*/AMotionEvent_getY(event, 1) + offset.y(),
         /*touch_major_pixels=*/AMotionEvent_getTouchMajor(event, 1),
         /*touch_minor_pixels=*/AMotionEvent_getTouchMinor(event, 1),
         /*pressure=*/AMotionEvent_getPressure(event, 1),
@@ -158,7 +158,7 @@
   }
 
   auto source = std::make_unique<MotionEventAndroidSourceNative>(
-      std::move(input_event), y_offset_pix);
+      std::move(input_event), offset);
 
   return base::WrapUnique<MotionEventAndroid>(new MotionEventAndroid(
       pix_to_dip,
diff --git a/ui/events/android/motion_event_android_factory.h b/ui/events/android/motion_event_android_factory.h
index a8d57b0..6a8c2759 100644
--- a/ui/events/android/motion_event_android_factory.h
+++ b/ui/events/android/motion_event_android_factory.h
@@ -14,6 +14,7 @@
 #include "base/time/time.h"
 #include "ui/events/android/motion_event_android.h"
 #include "ui/events/events_export.h"
+#include "ui/gfx/geometry/point_f.h"
 
 namespace ui {
 
@@ -72,7 +73,7 @@
   static std::unique_ptr<MotionEventAndroid> CreateFromNative(
       base::android::ScopedInputEvent input_event,
       float pix_to_dip,
-      float y_offset_pix,
+      gfx::PointF offset,
       std::optional<MotionEventAndroid::EventTimes> event_times);
 };
 
diff --git a/ui/events/android/motion_event_android_source_native.cc b/ui/events/android/motion_event_android_source_native.cc
index cdd5a42d..03530261 100644
--- a/ui/events/android/motion_event_android_source_native.cc
+++ b/ui/events/android/motion_event_android_source_native.cc
@@ -13,8 +13,8 @@
 
 MotionEventAndroidSourceNative::MotionEventAndroidSourceNative(
     base::android::ScopedInputEvent event,
-    float y_offset_pix)
-    : event_(std::move(event)), y_offset_pix_(y_offset_pix) {
+    gfx::PointF offset)
+    : event_(std::move(event)), offset_(offset) {
   CHECK(event_);
 }
 
@@ -25,12 +25,11 @@
 }
 
 float MotionEventAndroidSourceNative::GetXPix(size_t pointer_index) const {
-  return AMotionEvent_getX(event_.a_input_event(), pointer_index);
+  return AMotionEvent_getX(event_.a_input_event(), pointer_index) + offset_.x();
 }
 
 float MotionEventAndroidSourceNative::GetYPix(size_t pointer_index) const {
-  return AMotionEvent_getY(event_.a_input_event(), pointer_index) +
-         y_offset_pix_;
+  return AMotionEvent_getY(event_.a_input_event(), pointer_index) + offset_.y();
 }
 
 float MotionEventAndroidSourceNative::GetTouchMajorPix(
@@ -101,7 +100,8 @@
     size_t pointer_index,
     size_t historical_index) const {
   return AMotionEvent_getHistoricalX(event_.a_input_event(), pointer_index,
-                                     historical_index);
+                                     historical_index) +
+         offset_.x();
 }
 
 float MotionEventAndroidSourceNative::GetHistoricalYPix(
@@ -109,7 +109,7 @@
     size_t historical_index) const {
   return AMotionEvent_getHistoricalY(event_.a_input_event(), pointer_index,
                                      historical_index) +
-         y_offset_pix_;
+         offset_.y();
 }
 
 bool MotionEventAndroidSourceNative::IsLatestEventTimeResampled() const {
diff --git a/ui/events/android/motion_event_android_source_native.h b/ui/events/android/motion_event_android_source_native.h
index 3832a3a..d7a718e 100644
--- a/ui/events/android/motion_event_android_source_native.h
+++ b/ui/events/android/motion_event_android_source_native.h
@@ -9,6 +9,7 @@
 
 #include "base/android/scoped_input_event.h"
 #include "ui/events/android/motion_event_android_source.h"
+#include "ui/gfx/geometry/point_f.h"
 
 namespace ui {
 
@@ -16,7 +17,7 @@
 class MotionEventAndroidSourceNative : public MotionEventAndroidSource {
  public:
   MotionEventAndroidSourceNative(base::android::ScopedInputEvent event,
-                                 float y_offset_pix);
+                                 gfx::PointF offset);
 
   MotionEventAndroidSourceNative(const MotionEventAndroidSourceNative&) =
       delete;
@@ -55,7 +56,7 @@
 
  private:
   const base::android::ScopedInputEvent event_;
-  const float y_offset_pix_;
+  const gfx::PointF offset_;
 };
 
 }  // namespace ui
diff --git a/ui/events/android/motion_event_android_unittest.cc b/ui/events/android/motion_event_android_unittest.cc
index eea40de5..21b03583 100644
--- a/ui/events/android/motion_event_android_unittest.cc
+++ b/ui/events/android/motion_event_android_unittest.cc
@@ -20,6 +20,7 @@
 #include "ui/events/event_constants.h"
 #include "ui/events/test/motion_event_test_utils.h"
 #include "ui/events/test/scoped_event_test_tick_clock.h"
+#include "ui/gfx/geometry/point_f.h"
 
 // Must come after all headers that specialize FromJniType() / ToJniType().
 #include "ui/events/motionevent_jni_headers/MotionEvent_jni.h"
@@ -467,7 +468,7 @@
   std::unique_ptr<MotionEventAndroid> event =
       MotionEventAndroidFactory::CreateFromNative(
           base::android::ScopedInputEvent(native_event), kPixToDip,
-          /* y_offset_pix= */ 0,
+          /* offset= */ gfx::PointF(),
           /* event_times= */ std::nullopt);
 
   EXPECT_EQ(event->GetX(0), x * kPixToDip);
diff --git a/ui/events/platform/platform_event_source.h b/ui/events/platform/platform_event_source.h
index a628b8d..e7ab8f88 100644
--- a/ui/events/platform/platform_event_source.h
+++ b/ui/events/platform/platform_event_source.h
@@ -73,8 +73,12 @@
   virtual void ResetStateForTesting() {}
 
  protected:
-  typedef base::ObserverList<PlatformEventObserver>::Unchecked
-      PlatformEventObserverList;
+  // TODO(crbug.com/484371187): Investigate if reentrancy can be removed.
+  // See comment for `PlatformEventDispatcherList`.
+  using PlatformEventObserverList = base::ObserverList<
+      PlatformEventObserver,
+      /*check_empty=*/false,
+      base::ObserverListReentrancyPolicy::kAllowReentrancyUntriaged>::Unchecked;
 
   PlatformEventSource();
 
@@ -93,8 +97,13 @@
   // Use a base::ObserverList<> instead of an std::vector<> to store the list of
   // dispatchers, so that adding/removing dispatchers during an event dispatch
   // is well-defined.
-  using PlatformEventDispatcherList =
-      base::ObserverList<PlatformEventDispatcher>::Unchecked;
+  // TODO(crbug.com/484371187): Investigate if reentrancy can be removed.
+  // `WaylandTestBase::PostToServerAndWait` can trigger nested dispatch while
+  // waiting for another event's result.
+  using PlatformEventDispatcherList = base::ObserverList<
+      PlatformEventDispatcher,
+      /*check_empty=*/false,
+      base::ObserverListReentrancyPolicy::kAllowReentrancyUntriaged>::Unchecked;
 
   // This is invoked when the list of dispatchers changes (i.e. a new dispatcher
   // is added, or a dispatcher is removed).
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index a4e4367a1..ba4f798 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -776,6 +776,7 @@
       "font_fallback_mac_unittest.cc",
       "image/image_mac_unittest.mm",
       "mac/coordinate_conversion_unittest.mm",
+      "mac/display_icc_profiles_unittest.cc",
       "mac/io_surface_unittest.cc",
       "mac/menu_text_elider_mac_unittest.mm",
       "platform_font_mac_unittest.mm",
diff --git a/ui/gfx/mac/display_icc_profiles.cc b/ui/gfx/mac/display_icc_profiles.cc
index ccc9a89..914b80a9 100644
--- a/ui/gfx/mac/display_icc_profiles.cc
+++ b/ui/gfx/mac/display_icc_profiles.cc
@@ -17,6 +17,7 @@
 
 base::apple::ScopedCFTypeRef<CFDataRef>
 DisplayICCProfiles::GetDataForColorSpace(const ColorSpace& color_space) {
+  base::AutoLock lock(lock_);
   UpdateIfNeeded();
   base::apple::ScopedCFTypeRef<CFDataRef> result;
   auto found = map_.find(color_space);
@@ -41,8 +42,12 @@
   map_.clear();
 
   // Always add Apple's sRGB profile.
+  base::apple::ScopedCFTypeRef<CGColorSpaceRef> srgb_colorspace(
+      CGColorSpaceCreateWithName(kCGColorSpaceSRGB));
+  CHECK(srgb_colorspace);
   base::apple::ScopedCFTypeRef<CFDataRef> srgb_icc(
-      CGColorSpaceCopyICCData(CGColorSpaceCreateWithName(kCGColorSpaceSRGB)));
+      CGColorSpaceCopyICCData(srgb_colorspace.get()));
+  CHECK(srgb_icc);
   map_[ColorSpace::CreateSRGB()] = srgb_icc;
 
   // Add the profiles for all active displays.
@@ -88,6 +93,7 @@
     void* user_info) {
   DisplayICCProfiles* profiles =
       reinterpret_cast<DisplayICCProfiles*>(user_info);
+  base::AutoLock lock(profiles->lock_);
   profiles->needs_update_ = true;
 }
 
diff --git a/ui/gfx/mac/display_icc_profiles.h b/ui/gfx/mac/display_icc_profiles.h
index e0e0d49..4d1b72f 100644
--- a/ui/gfx/mac/display_icc_profiles.h
+++ b/ui/gfx/mac/display_icc_profiles.h
@@ -10,6 +10,7 @@
 #include "base/apple/scoped_cftyperef.h"
 #include "base/containers/flat_map.h"
 #include "base/no_destructor.h"
+#include "base/synchronization/lock.h"
 #include "ui/gfx/color_space.h"
 #include "ui/gfx/color_space_export.h"
 
@@ -49,10 +50,12 @@
   DisplayICCProfiles();
   ~DisplayICCProfiles();
 
-  void UpdateIfNeeded();
+  void UpdateIfNeeded() EXCLUSIVE_LOCKS_REQUIRED(lock_);
 
-  base::flat_map<ColorSpace, base::apple::ScopedCFTypeRef<CFDataRef>> map_;
-  bool needs_update_ = true;
+  base::flat_map<ColorSpace, base::apple::ScopedCFTypeRef<CFDataRef>> map_
+      GUARDED_BY(lock_);
+  bool needs_update_ GUARDED_BY(lock_) = true;
+  base::Lock lock_;
 };
 
 }  // namespace gfx
diff --git a/ui/gfx/mac/display_icc_profiles_unittest.cc b/ui/gfx/mac/display_icc_profiles_unittest.cc
new file mode 100644
index 0000000..beeecbe
--- /dev/null
+++ b/ui/gfx/mac/display_icc_profiles_unittest.cc
@@ -0,0 +1,24 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/mac/display_icc_profiles.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/color_space.h"
+
+namespace gfx {
+
+class DisplayICCProfilesTest : public testing::Test {};
+
+TEST_F(DisplayICCProfilesTest, Basic) {
+  DisplayICCProfiles* profiles = DisplayICCProfiles::GetInstance();
+  ColorSpace srgb = ColorSpace::CreateSRGB();
+
+  base::apple::ScopedCFTypeRef<CFDataRef> data =
+      profiles->GetDataForColorSpace(srgb);
+  // data should not be null because sRGB is always added.
+  EXPECT_TRUE(data);
+}
+
+}  // namespace gfx
diff --git a/ui/views/background.cc b/ui/views/background.cc
index 18de87c..410bc049 100644
--- a/ui/views/background.cc
+++ b/ui/views/background.cc
@@ -51,7 +51,7 @@
   }
 
   void OnViewThemeChanged(View* view) override {
-    if (color().IsSemantic()) {
+    if (color().IsLogical()) {
       view->SchedulePaint();
     }
   }
@@ -92,7 +92,7 @@
   }
 
   void OnViewThemeChanged(View* view) override {
-    if (color().IsSemantic()) {
+    if (color().IsLogical()) {
       view->SchedulePaint();
     }
   }
diff --git a/ui/views/border.cc b/ui/views/border.cc
index 112a192..24ee851a 100644
--- a/ui/views/border.cc
+++ b/ui/views/border.cc
@@ -91,7 +91,7 @@
 }
 
 void SolidSidedBorder::OnViewThemeChanged(View* view) {
-  if (color().IsSemantic()) {
+  if (color().IsLogical()) {
     view->SchedulePaint();
   }
 }
@@ -152,7 +152,7 @@
 }
 
 void RoundedRectBorder::OnViewThemeChanged(View* view) {
-  if (color().IsSemantic()) {
+  if (color().IsLogical()) {
     view->SchedulePaint();
   }
 }
diff --git a/ui/views/controls/image_view.cc b/ui/views/controls/image_view.cc
index faa243d..a3fe34a 100644
--- a/ui/views/controls/image_view.cc
+++ b/ui/views/controls/image_view.cc
@@ -80,7 +80,7 @@
   View::OnThemeChanged();
   if (image_model_.IsImageGenerator() ||
       (image_model_.IsVectorIcon() &&
-       image_model_.GetVectorIcon().color().IsSemantic())) {
+       image_model_.GetVectorIcon().color().IsLogical())) {
     scaled_image_ = gfx::ImageSkia();
     SchedulePaint();
   }
diff --git a/ui/webui/resources/cr_components/composebox/BUILD.gn b/ui/webui/resources/cr_components/composebox/BUILD.gn
index 0e7bfb54..2a8ff2a9 100644
--- a/ui/webui/resources/cr_components/composebox/BUILD.gn
+++ b/ui/webui/resources/cr_components/composebox/BUILD.gn
@@ -26,6 +26,8 @@
     "composebox.ts",
     "composebox_dropdown.html.ts",
     "composebox_dropdown.ts",
+    "composebox_file_inputs.html.ts",
+    "composebox_file_inputs.ts",
     "composebox_lens_search.html.ts",
     "composebox_lens_search.ts",
     "composebox_match.html.ts",
@@ -95,7 +97,7 @@
   ts_out_dir = "$root_gen_dir/ui/webui/resources/tsc/cr_components/composebox"
   ts_tsconfig_base = "tsconfig_base.json"
   ts_composite = true
-  ts_definitions = [ "//tools/typescript/definitions/metrics_private.d.ts" ]
+  ts_definitions = [ "//tools/typescript/definitions/chrome_histograms.d.ts" ]
   ts_deps = [
     "//third_party/lit/v3_0:build_ts",
     "//ui/webui/resources/cr_components/localized_link:build_ts",
diff --git a/ui/webui/resources/cr_components/composebox/common.ts b/ui/webui/resources/cr_components/composebox/common.ts
index 5415d7a1..ae4109e 100644
--- a/ui/webui/resources/cr_components/composebox/common.ts
+++ b/ui/webui/resources/cr_components/composebox/common.ts
@@ -71,30 +71,15 @@
 
 export function recordEnumerationValue(
     metricName: string, value: number, enumSize: number) {
-  // In rare cases chrome.metricsPrivate is not available.
-  // TODO(crbug.com/40162029): Remove this check once the bug is fixed.
-  if (!chrome.metricsPrivate) {
-    return;
-  }
-  chrome.metricsPrivate.recordEnumerationValue(metricName, value, enumSize);
+  chrome.histograms.recordEnumerationValue(metricName, value, enumSize);
 }
 
 export function recordUserAction(metricName: string) {
-  // In rare cases chrome.metricsPrivate is not available.
-  // TODO(crbug.com/40162029): Remove this check once the bug is fixed.
-  if (!chrome.metricsPrivate) {
-    return;
-  }
-  chrome.metricsPrivate.recordUserAction(metricName);
+  chrome.histograms.recordUserAction(metricName);
 }
 
 export function recordBoolean(metricName: string, value: boolean) {
-  // In rare cases chrome.metricsPrivate is not available.
-  // TODO(crbug.com/40162029): Remove this check once the bug is fixed.
-  if (!chrome.metricsPrivate) {
-    return;
-  }
-  chrome.metricsPrivate.recordBoolean(metricName, value);
+  chrome.histograms.recordBoolean(metricName, value);
 }
 
 // TODO(crbug.com/468329884): Consider making this a new contextual entry
diff --git a/ui/webui/resources/cr_components/composebox/composebox_file_inputs.html.ts b/ui/webui/resources/cr_components/composebox/composebox_file_inputs.html.ts
new file mode 100644
index 0000000..a0ec3af
--- /dev/null
+++ b/ui/webui/resources/cr_components/composebox/composebox_file_inputs.html.ts
@@ -0,0 +1,33 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {html} from '//resources/lit/v3_0/lit.rollup.js';
+
+import type {ComposeboxFileInputsElement} from './composebox_file_inputs.js';
+
+export function getHtml(this: ComposeboxFileInputsElement) {
+  // clang-format off
+  return html`<!--_html_template_start_-->
+${this.disableFileInputs ? html`<slot></slot>` : html`
+  <div id="fileUploadWrapper"
+    @open-image-upload="${this.openImageUpload_}"
+    @open-file-upload="${this.openFileUpload_}">
+    <slot></slot>
+  </div>
+  <input type="file"
+      accept="${this.imageFileTypes_}"
+      id="imageInput"
+      @change="${this.onFileChange_}"
+      hidden>
+  </input>
+  <input type="file"
+      accept="${this.attachmentFileTypes_}"
+      id="fileInput"
+      @change="${this.onFileChange_}"
+      hidden>
+  </input>
+`}
+<!--_html_template_end_-->`;
+  // clang-format off
+}
diff --git a/ui/webui/resources/cr_components/composebox/composebox_file_inputs.ts b/ui/webui/resources/cr_components/composebox/composebox_file_inputs.ts
new file mode 100644
index 0000000..66da0d4
--- /dev/null
+++ b/ui/webui/resources/cr_components/composebox/composebox_file_inputs.ts
@@ -0,0 +1,66 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {assert} from '//resources/js/assert.js';
+import {loadTimeData} from '//resources/js/load_time_data.js';
+import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js';
+
+import {getHtml} from './composebox_file_inputs.html.js';
+
+export interface ComposeboxFileInputsElement {
+  $: {
+    imageInput: HTMLInputElement,
+    fileInput: HTMLInputElement,
+  };
+}
+
+export class ComposeboxFileInputsElement extends CrLitElement {
+  static get is() {
+    return 'cr-composebox-file-inputs';
+  }
+
+  override render() {
+    return getHtml.bind(this)();
+  }
+
+  static override get properties() {
+    return {
+      disableFileInputs: {type: Boolean},
+      attachmentFileTypes_: {type: Array},
+      imageFileTypes_: {type: Array},
+    };
+  }
+
+  accessor disableFileInputs: boolean = false;
+  protected accessor attachmentFileTypes_: string[] =
+      loadTimeData.getString('composeboxAttachmentFileTypes').split(',');
+  protected accessor imageFileTypes_: string[] =
+      loadTimeData.getString('composeboxImageFileTypes').split(',');
+
+  protected openFileUpload_() {
+    assert(this.$.fileInput);
+    this.$.fileInput.click();
+  }
+
+  protected openImageUpload_() {
+    assert(this.$.imageInput);
+    this.$.imageInput.click();
+  }
+
+
+  protected onFileChange_(e: Event) {
+    const input = e.target as HTMLInputElement;
+    this.fire('on-file-change', {files: input.files});
+    input.value = '';
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'cr-composebox-file-inputs': ComposeboxFileInputsElement;
+  }
+}
+
+customElements.define(
+    ComposeboxFileInputsElement.is, ComposeboxFileInputsElement);
diff --git a/ui/webui/resources/cr_components/composebox/context_menu_entrypoint.css b/ui/webui/resources/cr_components/composebox/context_menu_entrypoint.css
index 48c80fe..06c8e41 100644
--- a/ui/webui/resources/cr_components/composebox/context_menu_entrypoint.css
+++ b/ui/webui/resources/cr_components/composebox/context_menu_entrypoint.css
@@ -368,21 +368,18 @@
 }
 
 .multi-tab-icon {
-  --iron-icon-height: 10px;
-  --iron-icon-width: 10px;
-  border-radius: 10px;
+  --iron-icon-height: 16px;
+  --iron-icon-width: 16px;
   flex-shrink: 0;
   margin-left: auto;
-  padding: 2px;
 }
 
 #multi-tab-add {
-  border: 1px solid;
+  color: var(--color-composebox-file-chip-text);
 }
 
 #multi-tab-check {
-  --iron-icon-fill-color: white;
-  background-color: var(--color-composebox-tab-selector-button-selected);
+  color: var(--color-composebox-tab-selector-button-selected);
 }
 
 @media (forced-colors: active) {
diff --git a/ui/webui/resources/cr_components/composebox/context_menu_entrypoint.html.ts b/ui/webui/resources/cr_components/composebox/context_menu_entrypoint.html.ts
index 3800ca8..b3ef01a 100644
--- a/ui/webui/resources/cr_components/composebox/context_menu_entrypoint.html.ts
+++ b/ui/webui/resources/cr_components/composebox/context_menu_entrypoint.html.ts
@@ -60,10 +60,10 @@
           ${this.enableMultiTabSelection_ ? html`
             ${this.disabledTabIds.has(tab.tabId) ? html`
               <cr-icon class="multi-tab-icon"
-                  icon="cr:check" id="multi-tab-check"></cr-icon>
+                  icon="composebox:checkCircle" id="multi-tab-check"></cr-icon>
             ` : html`
               <cr-icon class="multi-tab-icon"
-                  icon="cr:add" id="multi-tab-add"></cr-icon>
+                  icon="composebox:addCircle" id="multi-tab-add"></cr-icon>
             `}
           ` : ''}
         </button>
diff --git a/ui/webui/resources/cr_components/composebox/contextual_action_menu.css b/ui/webui/resources/cr_components/composebox/contextual_action_menu.css
index fcde6f7e..c9a55c4 100644
--- a/ui/webui/resources/cr_components/composebox/contextual_action_menu.css
+++ b/ui/webui/resources/cr_components/composebox/contextual_action_menu.css
@@ -124,21 +124,18 @@
 }
 
 .multi-tab-icon {
-  --iron-icon-height: 10px;
-  --iron-icon-width: 10px;
-  border-radius: 10px;
+  --iron-icon-height: 16px;
+  --iron-icon-width: 16px;
   flex-shrink: 0;
   margin-left: auto;
-  padding: 2px;
 }
 
 #multi-tab-add {
-  border: 1px solid;
+  color: var(--color-composebox-file-chip-text);
 }
 
 #multi-tab-check {
-  --iron-icon-fill-color: white;
-  background-color: var(--color-composebox-tab-selector-button-selected);
+  color: var(--color-composebox-tab-selector-button-selected);
 }
 
 #model-check {
diff --git a/ui/webui/resources/cr_components/composebox/contextual_action_menu.html.ts b/ui/webui/resources/cr_components/composebox/contextual_action_menu.html.ts
index 321748e4..1293345e 100644
--- a/ui/webui/resources/cr_components/composebox/contextual_action_menu.html.ts
+++ b/ui/webui/resources/cr_components/composebox/contextual_action_menu.html.ts
@@ -36,10 +36,10 @@
             ${this.enableMultiTabSelection_ ? html`
               ${this.disabledTabIds.has(tab.tabId) ? html`
                 <cr-icon class="multi-tab-icon"
-                    icon="cr:check" id="multi-tab-check"></cr-icon>
+                    icon="composebox:checkCircle" id="multi-tab-check"></cr-icon>
               ` : html`
                 <cr-icon class="multi-tab-icon"
-                    icon="cr:add" id="multi-tab-add"></cr-icon>
+                    icon="composebox:addCircle" id="multi-tab-add"></cr-icon>
               `}
             ` : ''}
           </button>
diff --git a/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel.html.ts b/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel.html.ts
index aee3d3e..1efc769d 100644
--- a/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel.html.ts
+++ b/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel.html.ts
@@ -13,6 +13,9 @@
 export function getHtml(this: ContextualEntrypointAndCarouselElement) {
   // clang-format off
   return html`<!--_html_template_start_-->
+<cr-composebox-file-inputs id="fileInputs"
+    @on-file-change="${this.onFileChange_}"
+    .disableFileInputs="${this.shouldDisableFileInputs_()}">
   ${this.searchboxLayoutMode === 'Compact' && !this.isOmniboxInCompactMode_ ?
     getContextMenuHtml.bind(this)()
   : ''}
@@ -48,18 +51,6 @@
   ${this.searchboxLayoutMode === 'TallBottomContext' || this.searchboxLayoutMode === '' || this.isOmniboxInCompactMode_ ? html`
     ${this.contextMenuEnabled_ ? getContextMenuHtml.bind(this)() : ''}
   `: ''}
-  <input type="file"
-      accept="${this.imageFileTypes_}"
-      id="imageInput"
-      @change="${this.onFileChange_}"
-      hidden>
-  </input>
-  <input type="file"
-      accept="${this.attachmentFileTypes_}"
-      id="fileInput"
-      @change="${this.onFileChange_}"
-      hidden>
-  </input>
   ${this.shouldShowVoiceSearchAtBottom_() ? html`
     <cr-icon-button id="voiceSearchButton" class="voice-icon" part="voice-icon"
         iron-icon="cr:mic" @click="${this.onVoiceSearchClick_}"
@@ -69,6 +60,7 @@
   ${this.submitButtonShown && this.searchboxLayoutMode === 'TallBottomContext' ?
       html`<slot name="submit-button"></slot>` :
       ''}
+</cr-composebox-file-inputs>
 <!--_html_template_end_-->`;
   // clang-format on
 }
diff --git a/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel.ts b/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel.ts
index bdaeb19d..cdecd2c5 100644
--- a/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel.ts
+++ b/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel.ts
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import './composebox_file_inputs.js';
 import './composebox_tool_chip.js';
 import './contextual_entrypoint_and_menu.js';
 import './contextual_entrypoint_button.js';
@@ -15,7 +16,6 @@
 import {ComposeboxContextAddedMethod} from '//resources/cr_components/search/constants.js';
 import type {CrIconButtonElement} from '//resources/cr_elements/cr_icon_button/cr_icon_button.js';
 import {I18nMixinLit} from '//resources/cr_elements/i18n_mixin_lit.js';
-import {assert} from '//resources/js/assert.js';
 import {loadTimeData} from '//resources/js/load_time_data.js';
 import type {PropertyValues} from '//resources/lit/v3_0/lit.rollup.js';
 import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js';
@@ -33,14 +33,14 @@
 import {getHtml} from './contextual_entrypoint_and_carousel.html.js';
 import type {ContextualEntrypointAndMenuElement} from './contextual_entrypoint_and_menu.js';
 import type {ComposeboxFileCarouselElement} from './file_carousel.js';
+import type {ComposeboxFileInputsElement} from './composebox_file_inputs.js';
 import type {RecentTabChipElement} from './recent_tab_chip.js';
 
 export interface ContextualEntrypointAndCarouselElement {
   $: {
-    fileInput: HTMLInputElement,
     contextEntrypoint: ContextualEntrypointAndMenuElement,
     carousel: ComposeboxFileCarouselElement,
-    imageInput: HTMLInputElement,
+    fileInputs: ComposeboxFileInputsElement,
     recentTabChip: RecentTabChipElement,
     voiceSearchButton: CrIconButtonElement,
   };
@@ -122,11 +122,9 @@
       // =========================================================================
       // Protected properties
       // =========================================================================
-      attachmentFileTypes_: {type: Array},
       contextMenuEnabled_: {type: Boolean},
       files_: {type: Object},
       addedTabsIds_: {type: Object},
-      imageFileTypes_: {type: Array},
       showContextMenuDescription_: {type: Boolean},
       showFileCarousel_: {
         reflect: true,
@@ -165,14 +163,10 @@
   accessor isOmniboxInCompactMode_: boolean = false;
   accessor recentTabForChip: TabInfo|null = null;
 
-  protected accessor attachmentFileTypes_: string[] =
-      loadTimeData.getString('composeboxAttachmentFileTypes').split(',');
   protected accessor contextMenuEnabled_: boolean =
       loadTimeData.getBoolean('composeboxShowContextMenu');
   protected accessor files_: Map<UnguessableToken, ComposeboxFile> = new Map();
   protected accessor addedTabsIds_: Map<number, UnguessableToken> = new Map();
-  protected accessor imageFileTypes_: string[] =
-      loadTimeData.getString('composeboxImageFileTypes').split(',');
   protected accessor uploadButtonDisabled_: boolean = false;
   protected contextMenuDescriptionEnabled_: boolean =
       loadTimeData.getBoolean('composeboxShowContextMenuDescription');
@@ -183,6 +177,10 @@
       ComposeboxToolMode.kUnspecified;
   protected accessor submitButtonShown: boolean = false;
   private automaticActiveTab_: ComposeboxFile|null = null;
+  private attachmentFileTypes_: string[] =
+      loadTimeData.getString('composeboxAttachmentFileTypes').split(',');
+  private imageFileTypes_: string[] =
+      loadTimeData.getString('composeboxImageFileTypes').split(',');
 
   getActiveToolMode() {
     return this.activeTool_;
@@ -612,11 +610,6 @@
       }
     }
 
-    if (context.attachments.length > 0) {
-      recordContextAdditionMethod(
-          ComposeboxContextAddedMethod.CONTEXT_MENU, this.composeboxSource_);
-    }
-
     switch (context.toolMode) {
       case ToolMode.kDeepSearch:
         this.setInitialMode(ComposeboxToolMode.kDeepSearch);
@@ -868,11 +861,8 @@
     this.handleProcessFilesError_(errorToDisplay);
   }
 
-  protected onFileChange_(e: Event) {
-    const input = e.target as HTMLInputElement;
-    const files = input.files;
-    this.processFiles_(files);
-    input.value = '';
+  protected onFileChange_(e: CustomEvent<{files: FileList}>) {
+    this.processFiles_(e.detail.files);
     recordContextAdditionMethod(
         ComposeboxContextAddedMethod.CONTEXT_MENU, this.composeboxSource_);
   }
@@ -924,22 +914,9 @@
     } as TabUpload);
   }
 
-  protected openImageUpload_() {
-    if (this.entrypointName !== 'ContextualTasks') {
-      // Open file dialog using top level primary window
-      // in contextual tasks composebox.
-      assert(this.$.imageInput);
-      this.$.imageInput.click();
-    }
-  }
-
-  protected openFileUpload_() {
-    if (this.entrypointName !== 'ContextualTasks') {
-      // Open file dialog using top level primary window
-      // in contextual tasks composebox.
-      assert(this.$.fileInput);
-      this.$.fileInput.click();
-    }
+  protected shouldDisableFileInputs_() {
+    return !this.contextMenuEnabled_ || !this.showMenuOnClick ||
+        this.entrypointName === 'ContextualTasks';
   }
 
   protected onToolClick_(e: CustomEvent<{toolMode: ComposeboxToolMode}>) {
diff --git a/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel_context_menu.html.ts b/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel_context_menu.html.ts
index 1376f088..e86c95e 100644
--- a/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel_context_menu.html.ts
+++ b/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel_context_menu.html.ts
@@ -21,8 +21,6 @@
         part="composebox-entrypoint"
         exportparts="context-menu-entrypoint-icon"
         class="upload-button no-overlap"
-        @open-image-upload="${this.openImageUpload_}"
-        @open-file-upload="${this.openFileUpload_}"
         @add-tab-context="${this.addTabContext_}"
         @delete-tab-context="${this.onDeleteFile_}"
         @tool-click="${this.onToolClick_}"
diff --git a/ui/webui/resources/cr_components/composebox/contextual_entrypoint_button.html.ts b/ui/webui/resources/cr_components/composebox/contextual_entrypoint_button.html.ts
index 730ea4a..0eb78fc 100644
--- a/ui/webui/resources/cr_components/composebox/contextual_entrypoint_button.html.ts
+++ b/ui/webui/resources/cr_components/composebox/contextual_entrypoint_button.html.ts
@@ -16,7 +16,8 @@
       <cr-button id="entrypoint" class="ai-mode-button" part="entrypoint-button"
           @click="${this.onEntrypointClick_}"
           title="${this.i18n('addContextTitle')}"
-          ?disabled="${this.uploadButtonDisabled}" noink>
+          ?disabled="${this.uploadButtonDisabled}" noink
+          aria-label="${this.i18n('addContextTitle')}">
         <cr-icon id="entrypointIcon" icon="cr:add" slot="prefix-icon"></cr-icon>
         <span id="description"
             @animationend="${this.onDescriptionAnimationEnd_}">
@@ -29,7 +30,8 @@
           iron-icon="cr:add"
           @click="${this.onEntrypointClick_}"
           title="${this.i18n('addContextTitle')}"
-          ?disabled="${this.uploadButtonDisabled}" noink>
+          ?disabled="${this.uploadButtonDisabled}" noink
+          aria-label="${this.i18n('addContextTitle')}">
       </cr-icon-button>
     `}
     ${this.glifAnimationState !== GlifAnimationState.INELIGIBLE ? html`
diff --git a/ui/webui/resources/cr_components/composebox/icons.html.ts b/ui/webui/resources/cr_components/composebox/icons.html.ts
index 9a569c1..7f6434abd 100644
--- a/ui/webui/resources/cr_components/composebox/icons.html.ts
+++ b/ui/webui/resources/cr_components/composebox/icons.html.ts
@@ -20,6 +20,12 @@
       <g id="fileUpload">
         <path d="M18 15.75C18 17.4833 17.3917 18.9583 16.175 20.175C14.9583 21.3917 13.4833 22 11.75 22C10.0167 22 8.54167 21.3917 7.325 20.175C6.10833 18.9583 5.5 17.4833 5.5 15.75V6.5C5.5 5.25 5.93333 4.19167 6.8 3.325C7.68333 2.44167 8.75 2 10 2C11.25 2 12.3083 2.44167 13.175 3.325C14.0583 4.19167 14.5 5.25 14.5 6.5V15.25C14.5 16.0167 14.2333 16.6667 13.7 17.2C13.1667 17.7333 12.5167 18 11.75 18C10.9833 18 10.3333 17.7333 9.8 17.2C9.26667 16.6667 9 16.0167 9 15.25V6H11V15.25C11 15.4667 11.0667 15.65 11.2 15.8C11.35 15.9333 11.5333 16 11.75 16C11.9667 16 12.1417 15.9333 12.275 15.8C12.425 15.65 12.5 15.4667 12.5 15.25V6.5C12.4833 5.8 12.2333 5.20833 11.75 4.725C11.2833 4.24167 10.7 4 10 4C9.3 4 8.70833 4.24167 8.225 4.725C7.74167 5.20833 7.5 5.8 7.5 6.5V15.75C7.48333 16.9333 7.89167 17.9417 8.725 18.775C9.55833 19.5917 10.5667 20 11.75 20C12.9167 20 13.9083 19.5917 14.725 18.775C15.5417 17.9417 15.9667 16.9333 16 15.75V6H18V15.75Z" fill="currentColor"/>
       </g>
+      <g id="addCircle" viewBox="0 -960 960 960">
+        <path d="M440-280h80v-160h160v-80H520v-160h-80v160H280v80h160v160Zm40 200q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z" fill="currentColor"/>
+      </g>
+      <g id="checkCircle" viewBox="0 -960 960 960">
+        <path d="m424-296 282-282-56-56-226 226-114-114-56 56 170 170Zm56 216q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Z" fill="currentColor"/>
+      </g>
       <g id="canvas" viewBox="0 0 16 16">
         <path d="M11.6 14.4H7.6C7.6 14.2111 7.6 14.0222 7.6 13.8333C7.6 13.6333 7.6 13.4222 7.6 13.2H11.6V5.6H8.8V2.8H4.4V8.4C4.26667 8.4 4.13333 8.4 4 8.4C3.86667 8.4 3.72778 8.4 3.58333 8.4C3.51667 8.4 3.45 8.4 3.38333 8.4C3.32778 8.4 3.26667 8.4 3.2 8.4V2.8C3.2 2.46667 3.31667 2.18333 3.55 1.95C3.78333 1.71667 4.06667 1.6 4.4 1.6H9.6L12.8 4.8V13.2C12.8 13.5333 12.6833 13.8167 12.45 14.05C12.2167 14.2833 11.9333 14.4 11.6 14.4ZM3.58333 15.2C3.57222 15.2 3.52778 15.1667 3.45 15.1C3.29444 14.4667 2.98333 13.9222 2.51667 13.4667C2.06111 13 1.51667 12.6889 0.883333 12.5333C0.861111 12.5222 0.827778 12.4778 0.783333 12.4C0.783333 12.3778 0.816667 12.3333 0.883333 12.2667C1.51667 12.1111 2.06111 11.8056 2.51667 11.35C2.98333 10.8833 3.29444 10.3333 3.45 9.7C3.46111 9.67778 3.50556 9.64444 3.58333 9.6C3.60556 9.6 3.65 9.63333 3.71667 9.7C3.88333 10.3333 4.19444 10.8778 4.65 11.3333C5.10556 11.7889 5.65 12.1 6.28333 12.2667C6.30556 12.2667 6.33889 12.3111 6.38333 12.4C6.38333 12.4111 6.35 12.4556 6.28333 12.5333C5.65 12.6889 5.1 13 4.63333 13.4667C4.17778 13.9222 3.87222 14.4667 3.71667 15.1C3.71667 15.1222 3.67222 15.1556 3.58333 15.2Z" fill="currentColor"/>
       </g>
diff --git a/ui/webui/resources/cr_components/cr_shortcut_input/cr_shortcut_input.css b/ui/webui/resources/cr_components/cr_shortcut_input/cr_shortcut_input.css
index fab44b0..e3093c3 100644
--- a/ui/webui/resources/cr_components/cr_shortcut_input/cr_shortcut_input.css
+++ b/ui/webui/resources/cr_components/cr_shortcut_input/cr_shortcut_input.css
@@ -23,6 +23,7 @@
   --cr-input-error-display: none;
 }
 
-#edit {
+#edit,
+#clear {
   margin-inline-start: var(--cr-icon-ripple-padding);
 }
diff --git a/ui/webui/resources/cr_components/cr_shortcut_input/cr_shortcut_input.html.ts b/ui/webui/resources/cr_components/cr_shortcut_input/cr_shortcut_input.html.ts
index 741ec6e3..dcb17aa 100644
--- a/ui/webui/resources/cr_components/cr_shortcut_input/cr_shortcut_input.html.ts
+++ b/ui/webui/resources/cr_components/cr_shortcut_input/cr_shortcut_input.html.ts
@@ -21,9 +21,15 @@
     <cr-icon-button id="edit" title="${this.i18n('edit')}"
         aria-label="${this.editButtonAriaLabel}"
         slot="suffix" class="icon-edit no-overlap"
-        ?disabled="${this.inputDisabled}"
+        ?disabled="${this.inputDisabled || !this.readonly_}"
         @click="${this.onEditClick_}">
     </cr-icon-button>
+    <cr-icon-button id="clear" title="${this.i18n('shortcutClear')}"
+        aria-label="${this.clearButtonAriaLabel}"
+        slot="suffix" class="icon-clear no-overlap"
+        ?disabled="${this.inputDisabled || !this.shortcut}"
+        @click="${this.onClearClick_}">
+    </cr-icon-button>
   </cr-input>
 </div>
 <!--_html_template_end_-->`;
diff --git a/ui/webui/resources/cr_components/cr_shortcut_input/cr_shortcut_input.ts b/ui/webui/resources/cr_components/cr_shortcut_input/cr_shortcut_input.ts
index e0cd46d..4518893 100644
--- a/ui/webui/resources/cr_components/cr_shortcut_input/cr_shortcut_input.ts
+++ b/ui/webui/resources/cr_components/cr_shortcut_input/cr_shortcut_input.ts
@@ -30,6 +30,7 @@
   $: {
     input: CrInputElement,
     edit: CrIconButtonElement,
+    clear: CrIconButtonElement,
   };
 }
 
@@ -53,6 +54,7 @@
       shortcut: {type: String},
       inputAriaLabel: {type: String},
       editButtonAriaLabel: {type: String},
+      clearButtonAriaLabel: {type: String},
       inputDisabled: {type: Boolean},
       allowCtrlAltShortcuts: {type: Boolean},
       error_: {type: Number},
@@ -67,6 +69,7 @@
   accessor shortcut: string = '';
   accessor inputAriaLabel: string = '';
   accessor editButtonAriaLabel: string = '';
+  accessor clearButtonAriaLabel: string = '';
   accessor inputDisabled: boolean = false;
   accessor allowCtrlAltShortcuts = false;
   protected accessor readonly_: boolean = true;
@@ -109,12 +112,18 @@
     this.fire('input-capture-change', false);
   }
 
-  private clearShortcut_() {
+  private async clearShortcut_() {
     this.pendingShortcut_ = '';
-    this.shortcut = '';
     // Commit the empty shortcut in order to clear the current shortcut.
-    this.commitPending_();
-    this.endCapture_();
+    await this.commitPending_();
+    if (this.capturing_) {
+      // Cleared while an edit was in progress - perform proper cleanup.
+      await this.endCapture_();
+    } else {
+      // Cleared while not capturing - just fire the event to signal to the
+      // page that the shortcut has been cleared.
+      this.fire('input-capture-change', false);
+    }
   }
 
   private onKeyDown_(e: KeyboardEvent) {
@@ -252,7 +261,7 @@
     if (this.inputDisabled) {
       return this.i18n('setShortcutInSystemSettings');
     }
-    return formatShortcutText(this.shortcut);
+    return formatShortcutText(this.readonly_ ? this.shortcut : '');
   }
 
   protected getIsInvalid_(): boolean {
@@ -260,13 +269,13 @@
   }
 
   protected onEditClick_() {
-    // TODO(ghazale): The clearing functionality should be improved.
-    // Instead of clicking the edit button, and then clicking elsewhere to
-    // commit the "empty" shortcut, introduce a separate clear button.
-    this.clearShortcut_();
     this.readonly_ = false;
     this.$.input.focus();
   }
+
+  protected onClearClick_() {
+    void this.clearShortcut_();
+  }
 }
 
 declare global {
diff --git a/ui/webui/resources/cr_components/searchbox/BUILD.gn b/ui/webui/resources/cr_components/searchbox/BUILD.gn
index fe45ebe..65a45216 100644
--- a/ui/webui/resources/cr_components/searchbox/BUILD.gn
+++ b/ui/webui/resources/cr_components/searchbox/BUILD.gn
@@ -43,7 +43,7 @@
 
   ts_out_dir = "$root_gen_dir/ui/webui/resources/tsc/cr_components/searchbox"
   ts_composite = true
-  ts_definitions = [ "//tools/typescript/definitions/metrics_private.d.ts" ]
+  ts_definitions = [ "//tools/typescript/definitions/chrome_histograms.d.ts" ]
   ts_deps = [
     "//third_party/lit/v3_0:build_ts",
     "//ui/webui/resources/cr_components/composebox:build_ts",
diff --git a/ui/webui/resources/cr_components/searchbox/searchbox.ts b/ui/webui/resources/cr_components/searchbox/searchbox.ts
index 196437ba..556c2d7 100644
--- a/ui/webui/resources/cr_components/searchbox/searchbox.ts
+++ b/ui/webui/resources/cr_components/searchbox/searchbox.ts
@@ -1113,8 +1113,8 @@
       }
       const metricName =
           `ContextualSearch.UserAction.SubmitQuery.WithoutContext.${source}`;
-      chrome.metricsPrivate.recordUserAction(metricName);
-      chrome.metricsPrivate.recordBoolean(metricName, true);
+      chrome.histograms.recordUserAction(metricName);
+      chrome.histograms.recordBoolean(metricName, true);
 
       // Construct navigation url.
       const searchParams = new URLSearchParams();
@@ -1144,7 +1144,7 @@
       this.openComposebox_();
     }
 
-    chrome.metricsPrivate.recordBoolean(
+    chrome.histograms.recordBoolean(
         'NewTabPage.ComposeEntrypoint.Click.UserTextPresent',
         !this.isInputEmpty());
   }
diff --git a/url/android/javatests/src/org/chromium/url/GURLJavaTest.java b/url/android/javatests/src/org/chromium/url/GURLJavaTest.java
index 66ff2ebc..7fb03edc 100644
--- a/url/android/javatests/src/org/chromium/url/GURLJavaTest.java
+++ b/url/android/javatests/src/org/chromium/url/GURLJavaTest.java
@@ -11,10 +11,12 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.util.Batch;
@@ -33,9 +35,10 @@
 public class GURLJavaTest {
     @Mock GURL.Natives mGURLMocks;
 
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
 
         NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
         GURLJavaTestHelper.nativeInitializeICU();
diff --git a/v8 b/v8
index b8acdbd..018afda 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit b8acdbdf77d8196d2917ed4e8d8aef8329068904
+Subproject commit 018afda931c627de446796ce6a0d38da3fd038c3