diff --git a/.gn b/.gn
index abfda1c..c268132 100644
--- a/.gn
+++ b/.gn
@@ -195,7 +195,6 @@
   # //third_party/blink/*, https://crbug.com/800764
   "//third_party/blink/renderer/core/animation:*",  # 506 errors
   "//third_party/blink/renderer/core/exported:*",  # 470 errors
-  "//third_party/blink/renderer/core/probe:*",  # 9 errors
 
   "//third_party/breakpad:*",  # 34 errors
   "//third_party/ced/*",
diff --git a/DEPS b/DEPS
index ca6471b..b9d2498 100644
--- a/DEPS
+++ b/DEPS
@@ -206,7 +206,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '312535b47d389e55a6666ea82638458245a421e0',
+  'skia_revision': 'aea82732415c78b5182f78909738782b9b2e18f1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -218,7 +218,7 @@
   # 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': '7a0263547cda936b320d80c650b69d7522ee1a9f',
+  'angle_revision': '0cec8f7429b432b73cc9a3fb9e6a831792743582',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -226,7 +226,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '153af9451acd5eead2a07d144517d2a9349d72fb',
+  'pdfium_revision': 'f6b755916fcf9c927881cc7667a89f09f857ac31',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -277,7 +277,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': '754b80c7bb21908da53324853fb970a7c4949c15',
+  'devtools_frontend_revision': '95f8e66392b8aa1005af7803d38240ee30612fe8',
   # 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.
@@ -313,7 +313,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.
-  'spv_tools_revision': '69f07da41b3bc4f563fade2b2d9aeab7f3329ae4',
+  'spv_tools_revision': 'abe2eff36f3cefa15eec98d9f08e12e05493966e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -1497,7 +1497,7 @@
   },
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '3065e6ef3016a906d1db82e1d4322cbd53d43247',
+    Var('webrtc_git') + '/src.git' + '@' + 'e6fa238f76e50a8caa0547074f75443bbfd7b986',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1569,7 +1569,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@aab438856f5f39fe087f989e69b914b5fea27279',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@82a2948010cbeb8333a36c020f6d695af372dc0d',
     'condition': 'checkout_src_internal',
   },
 
@@ -1588,7 +1588,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': '3QUpvk4I1p2BBj5QhBEW9fkqEdtru4Sl0wIbbsNU6SkC',
+        'version': '8FLJniKLOIvgXmnehF5KQa4m-kep06p-rTGFZXejsuoC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/shortcut_viewer/keyboard_shortcut_item.cc b/ash/shortcut_viewer/keyboard_shortcut_item.cc
index f9e1b86..180d7d1 100644
--- a/ash/shortcut_viewer/keyboard_shortcut_item.cc
+++ b/ash/shortcut_viewer/keyboard_shortcut_item.cc
@@ -18,7 +18,7 @@
 KeyboardShortcutItem::KeyboardShortcutItem(
     const std::vector<ShortcutCategory>& categories,
     int description_message_id,
-    int shortcut_message_id,
+    base::Optional<int> shortcut_message_id,
     const std::vector<AcceleratorId>& accelerator_ids,
     const std::vector<ui::KeyboardCode>& shortcut_key_codes)
     : categories(categories),
diff --git a/ash/shortcut_viewer/keyboard_shortcut_item.h b/ash/shortcut_viewer/keyboard_shortcut_item.h
index be708cd..eca73fb24 100644
--- a/ash/shortcut_viewer/keyboard_shortcut_item.h
+++ b/ash/shortcut_viewer/keyboard_shortcut_item.h
@@ -9,6 +9,7 @@
 
 #include "ash/shortcut_viewer/ksv_export.h"
 #include "base/macros.h"
+#include "base/optional.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 
 namespace keyboard_shortcut_viewer {
@@ -56,7 +57,7 @@
   KeyboardShortcutItem(
       const std::vector<ShortcutCategory>& categories,
       int description_message_id,
-      int shortcut_message_id,
+      base::Optional<int> shortcut_message_id,
       const std::vector<AcceleratorId>& accelerator_ids = {},
       const std::vector<ui::KeyboardCode>& shortcut_key_codes = {});
   explicit KeyboardShortcutItem(const KeyboardShortcutItem& other);
@@ -70,7 +71,9 @@
 
   // Id of the message template resource used to list the keys making up the
   // shortcut.
-  int shortcut_message_id;
+  // If missing, automatically determine the ID based on the number of
+  // `shortcut_key_codes`.
+  base::Optional<int> shortcut_message_id;
 
   // Multiple accelerators can be mapped to the same KeyboardShortcutItem.
   // |shortcut_key_codes| could be auto-generated from |accelerator_ids| to
diff --git a/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc b/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
index 6d79c68..2fadecc0 100644
--- a/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
+++ b/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
@@ -213,35 +213,35 @@
       {// |categories|
        {ShortcutCategory::kAccessibility},
        IDS_KSV_DESCRIPTION_TOGGLE_DOCKED_MAGNIFIER,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_D, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kAccessibility},
        IDS_KSV_DESCRIPTION_TOGGLE_FULLSCREEN_MAGNIFIER,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_M, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPopular},
        IDS_KSV_DESCRIPTION_LOCK_SCREEN,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_L, ui::EF_COMMAND_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_DISPLAY_ZOOM_OUT,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_MINUS, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_DISPLAY_ZOOM_IN,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_PLUS, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN}}},
 
@@ -286,42 +286,42 @@
       {// |categories|
        {ShortcutCategory::kAccessibility},
        IDS_KSV_DESCRIPTION_FOCUS_SHELF,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_L, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_BOOKMARK_ALL_TABS,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_D, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_BOOKMARK_THIS_TAB,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_D, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_IDC_CLOSE_TAB,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_W, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_IDC_CLOSE_WINDOW,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_IDC_CONTENT_CONTEXT_SELECTALL,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -330,21 +330,21 @@
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_DEV_TOOLS,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_DEV_TOOLS_CONSOLE,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_J, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_FIND,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_F, ui::EF_CONTROL_DOWN}}},
 
@@ -370,7 +370,7 @@
       {// |categories|
        {ShortcutCategory::kPageAndBrowser, ShortcutCategory::kAccessibility},
        IDS_KSV_DESCRIPTION_IDC_FOCUS_BOOKMARKS,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN}}},
 
@@ -396,63 +396,63 @@
       {// |categories|
        {ShortcutCategory::kAccessibility},
        IDS_KSV_DESCRIPTION_IDC_FOCUS_TOOLBAR,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_KEYBOARD_BRIGHTNESS_DOWN,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_BRIGHTNESS_DOWN, ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_KEYBOARD_BRIGHTNESS_UP,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_BRIGHTNESS_UP, ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_LAUNCH_LAST_APP,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_9, ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPopular, ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_NEW_TAB,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_T, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPopular, ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_NEW_WINDOW,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_N, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_IDC_NEW_INCOGNITO_WINDOW,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_N, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_IDC_OPEN_FILE,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_O, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_PRINT,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_P, ui::EF_CONTROL_DOWN}}},
 
@@ -469,77 +469,77 @@
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_RELOAD_BYPASSING_CACHE,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_R, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_IDC_RESTORE_TAB,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_BACK,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_LEFT, ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_FORWARD,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_RIGHT, ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_SAVE_PAGE,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_S, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_IDC_SELECT_LAST_TAB,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_9, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPopular},
        IDS_KSV_DESCRIPTION_IDC_SELECT_NEXT_TAB,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_TAB, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPopular},
        IDS_KSV_DESCRIPTION_IDC_SELECT_PREVIOUS_TAB,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_SHOW_BOOKMARK_BAR,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_SHOW_HISTORY,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_H, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_CLOSE_FIND_OR_STOP,
-       IDS_KSV_SHORTCUT_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -548,160 +548,160 @@
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_VIEW_SOURCE,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_U, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_ZOOM_MINUS,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_MINUS, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_ZOOM_NORMAL,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_0, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_ZOOM_PLUS,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_PLUS, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay, ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_SWITCH_TO_NEXT_IME,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_SPACE, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_OPEN_FILE_MANAGER,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_M, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay, ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_SWITCH_TO_LAST_USED_IME,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_SPACE, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_ROTATE_SCREEN,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_BROWSER_REFRESH, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_SCALE_UI_RESET,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_0, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_SWITCH_TO_NEXT_USER,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_PERIOD, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_SWITCH_TO_PREVIOUS_USER,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_COMMA, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPopular},
        IDS_KSV_DESCRIPTION_TAKE_PARTIAL_SCREENSHOT,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPopular},
        IDS_KSV_DESCRIPTION_TAKE_SCREENSHOT,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPopular, ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_TOGGLE_CAPS_LOCK,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_LWIN, ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kAccessibility},
        IDS_KSV_DESCRIPTION_TOGGLE_HIGH_CONTRAST,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_H, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kAccessibility},
        IDS_KSV_DESCRIPTION_CARET_BROWSING_TOGGLE,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_7, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_TOGGLE_MESSAGE_CENTER_BUBBLE,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_N, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPopular},
        IDS_KSV_DESCRIPTION_TOGGLE_OVERVIEW,
-       IDS_KSV_SHORTCUT_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_NONE}}},
 
       {// |categories|
        {ShortcutCategory::kAccessibility},
        IDS_KSV_DESCRIPTION_TOGGLE_SPOKEN_FEEDBACK,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_Z, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_TOGGLE_SYSTEM_TRAY_BUBBLE,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_S, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_WINDOW_CYCLE_SNAP_LEFT,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_4, ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_WINDOW_CYCLE_SNAP_RIGHT,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_6, ui::EF_ALT_DOWN}}},
       {// |categories|
        {ShortcutCategory::kPopular, ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_CLIPBOARD_HISTORY,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -709,7 +709,7 @@
       {// |categories|
        {ShortcutCategory::kPopular, ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_COPY,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -718,7 +718,7 @@
       {// |categories|
        {ShortcutCategory::kPopular, ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_PASTE,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -736,7 +736,7 @@
       {// |categories|
        {ShortcutCategory::kPopular},
        IDS_KSV_DESCRIPTION_KEYBOARD_SHORTCUT_HELPER,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_2, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN}}},
 
@@ -786,7 +786,7 @@
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_PAGE_UP,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -795,7 +795,7 @@
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_PAGE_DOWN,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -804,7 +804,7 @@
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_SCROLL_DOWN_PAGE,
-       IDS_KSV_SHORTCUT_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -813,7 +813,7 @@
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_GO_TO_TOP,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -823,7 +823,7 @@
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_GO_TO_BOTTOM,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -849,7 +849,7 @@
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_AUTO_COMPLETE,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -858,7 +858,7 @@
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_OPEN_DOWNLOADS_PAGE,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_J, ui::EF_CONTROL_DOWN}}},
 
@@ -874,7 +874,7 @@
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_DISPLAY_HIDDEN_FILES,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -911,7 +911,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_SELECT_NEXT_WORD,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -921,7 +921,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_SELECT_TEXT_TO_END_OF_LINE,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -931,7 +931,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_SELECT_TEXT_TO_BEGINNING,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -941,7 +941,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_SELECT_PREVIOUS_WORD,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -951,7 +951,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_MOVE_TO_END_OF_WORD,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -960,7 +960,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_MOVE_TO_START_OF_PREVIOUS_WORD,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -969,7 +969,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_GO_TO_END_OF_DOCUMENT,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -979,7 +979,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_GO_TO_END_OF_LINE,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -988,7 +988,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_GO_TO_BEGINNING_OF_DOCUMENT,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -998,7 +998,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_GO_TO_BEGINNING_OF_LINE,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -1007,7 +1007,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_PASTE_CONTENT_AS_TEXT,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -1017,7 +1017,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_CUT,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -1026,7 +1026,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_DELETE_PREVIOUS_WORD,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -1035,7 +1035,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_DELETE_NEXT_WORD,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -1044,7 +1044,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_UNDO,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -1053,7 +1053,7 @@
       {// |categories|
        {ShortcutCategory::kTextEditing},
        IDS_KSV_DESCRIPTION_REDO,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -1105,7 +1105,7 @@
       {// |categories|
        {ShortcutCategory::kAccessibility},
        IDS_KSV_DESCRIPTION_OPEN_RIGHT_CLICK_MENU_FOR_HIGHLIGHTED_ITEM,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {},
        // |shortcut_key_codes|
@@ -1115,154 +1115,154 @@
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_TOGGLE_MIRROR_MODE,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_SWAP_PRIMARY_DISPLAY,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_BRIGHTNESS_DOWN,
-       IDS_KSV_SHORTCUT_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_BRIGHTNESS_UP,
-       IDS_KSV_SHORTCUT_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE}}},
 
       {// |categories|
        {ShortcutCategory::kAccessibility},
        IDS_KSV_DESCRIPTION_MAGNIFY_SCREEN_ZOOM_OUT,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_BRIGHTNESS_DOWN, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kAccessibility},
        IDS_KSV_DESCRIPTION_MAGNIFY_SCREEN_ZOOM_IN,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_BRIGHTNESS_UP, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_VOLUME_MUTE,
-       IDS_KSV_SHORTCUT_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_VOLUME_MUTE, ui::EF_NONE}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_VOLUME_DOWN,
-       IDS_KSV_SHORTCUT_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_VOLUME_DOWN, ui::EF_NONE}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_VOLUME_UP,
-       IDS_KSV_SHORTCUT_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_VOLUME_UP, ui::EF_NONE}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_SHOW_TASK_MANAGER,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_ESCAPE, ui::EF_COMMAND_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_TOGGLE_FULLSCREEN,
-       IDS_KSV_SHORTCUT_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_NONE}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_WINDOW_MINIMIZE,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_MINUS, ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_FOCUS_NEXT_PANE,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_BROWSER_BACK, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_FOCUS_PREVIOUS_PANE,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_BROWSER_BACK, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_MOVE_ACTIVE_WINDOW_BETWEEN_DISPLAYS,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_M, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_TOGGLE_APP_LIST,
-       IDS_KSV_SHORTCUT_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_LWIN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_TOGGLE_APP_LIST_FULLSCREEN,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_LWIN, ui::EF_SHIFT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_TAKE_WINDOW_SCREENSHOT,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_SUSPEND,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_L, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_OPEN_GET_HELP,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_2, ui::EF_CONTROL_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_OPEN_FEEDBACK_PAGE,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_I, ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_ROTATE_WINDOW,
-       IDS_KSV_SHORTCUT_THREE_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_BROWSER_REFRESH,
          ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN}}},
@@ -1270,123 +1270,123 @@
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_SHOW_STYLUS_TOOLS,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_P, ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_TOGGLE_MAXIMIZED,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_PLUS, ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_OPEN_CROSH,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_T, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_EXIT,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_Q, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_UNPIN,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_SHOW_IME_MENU_BUBBLE,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_K, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_DESKS_NEW_DESK,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_PLUS, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN}}},
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_DESKS_REMOVE_CURRENT_DESK,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_MINUS, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_DESKS_ACTIVATE_LEFT_DESK,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_4, ui::EF_COMMAND_DOWN}}},
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_DESKS_ACTIVATE_RIGHT_DESK,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_6, ui::EF_COMMAND_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_DESKS_MOVE_ACTIVE_ITEM_LEFT_DESK,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_4, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN}}},
       {// |categories|
        {ShortcutCategory::kTabAndWindow},
        IDS_KSV_DESCRIPTION_DESKS_MOVE_ACTIVE_ITEM_RIGHT_DESK,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_OEM_6, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_SHOW_IDC_FOCUS_MENU_BAR,
-       IDS_KSV_SHORTCUT_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_F10}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_SHOW_IDC_HOME,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_HOME, ui::EF_ALT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_SHOW_IDC_CLEAR_BROWSING_DATA,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_BACK, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_SHOW_IDC_SHOW_BOOKMARK_MANAGER,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_O, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kPageAndBrowser},
        IDS_KSV_DESCRIPTION_IDC_DEV_TOOLS_INSPECT,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_C, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN}}},
 
       {// |categories|
        {ShortcutCategory::kAccessibility},
        IDS_KSV_DESCRIPTION_IDC_FOCUS_INACTIVE_POPUP_FOR_ACCESSIBILITY,
-       IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_A, ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN}}},
 
@@ -1402,7 +1402,7 @@
       {// |categories|
        {ShortcutCategory::kPopular},
        IDS_KSV_DESCRIPTION_OPEN_GOOGLE_ASSISTANT,
-       IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_A, ui::EF_COMMAND_DOWN}}},
 
@@ -1429,7 +1429,7 @@
       {// |categories|
        {ShortcutCategory::kSystemAndDisplay},
        IDS_KSV_DESCRIPTION_PRIVACY_SCREEN_TOGGLE,
-       IDS_KSV_SHORTCUT_ONE_KEY,
+       {},
        // |accelerator_ids|
        {{ui::VKEY_PRIVACY_SCREEN_TOGGLE, ui::EF_NONE}}},
   });
diff --git a/ash/shortcut_viewer/views/keyboard_shortcut_item_view.cc b/ash/shortcut_viewer/views/keyboard_shortcut_item_view.cc
index 8421d6f..b682748 100644
--- a/ash/shortcut_viewer/views/keyboard_shortcut_item_view.cc
+++ b/ash/shortcut_viewer/views/keyboard_shortcut_item_view.cc
@@ -14,6 +14,7 @@
 #include "ash/shortcut_viewer/views/bubble_view.h"
 #include "base/i18n/rtl.h"
 #include "base/no_destructor.h"
+#include "base/notreached.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -100,18 +101,44 @@
                                                        : accessible_name);
   }
 
+  int shortcut_message_id;
+  if (item.shortcut_message_id) {
+    shortcut_message_id = *item.shortcut_message_id;
+  } else {
+    // Automatically determine the shortcut message based on the number of
+    // shortcut_key_codes.
+    // As there are separators inserted between the modifiers, a shortcut with
+    // N modifiers has 2*N + 1 shortcut_key_codes.
+    switch (item.shortcut_key_codes.size()) {
+      case 1:
+        shortcut_message_id = IDS_KSV_SHORTCUT_ONE_KEY;
+        break;
+      case 3:
+        shortcut_message_id = IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY;
+        break;
+      case 5:
+        shortcut_message_id = IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY;
+        break;
+      case 7:
+        shortcut_message_id = IDS_KSV_SHORTCUT_THREE_MODIFIERS_ONE_KEY;
+        break;
+      default:
+        NOTREACHED() << "Automatically determined shortcut has "
+                     << item.shortcut_key_codes.size() << " key codes.";
+    }
+  }
+
   base::string16 shortcut_string;
   base::string16 accessible_string;
   if (replacement_strings.empty()) {
-    shortcut_string = l10n_util::GetStringUTF16(has_invalid_dom_key
-                                                    ? IDS_KSV_KEY_NO_MAPPING
-                                                    : item.shortcut_message_id);
+    shortcut_string = l10n_util::GetStringUTF16(
+        has_invalid_dom_key ? IDS_KSV_KEY_NO_MAPPING : shortcut_message_id);
     accessible_string = shortcut_string;
   } else {
-    shortcut_string = l10n_util::GetStringFUTF16(item.shortcut_message_id,
+    shortcut_string = l10n_util::GetStringFUTF16(shortcut_message_id,
                                                  replacement_strings, &offsets);
     accessible_string = l10n_util::GetStringFUTF16(
-        item.shortcut_message_id, accessible_names, /*offsets=*/nullptr);
+        shortcut_message_id, accessible_names, /*offsets=*/nullptr);
   }
   shortcut_label_view_ = AddChildView(std::make_unique<views::StyledLabel>());
   shortcut_label_view_->SetText(shortcut_string);
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 221fd157..e8257f5 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20201024.3.1
+0.20201026.0.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 221fd157..e8257f5 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20201024.3.1
+0.20201026.0.1
diff --git a/chrome/VERSION b/chrome/VERSION
index 8bfb1d0..5ee8429f 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=88
 MINOR=0
-BUILD=4303
+BUILD=4305
 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index b66607e4..fcc0d4e 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -1556,7 +1556,6 @@
   "java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandler.java",
   "java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java",
   "java/src/org/chromium/chrome/browser/toolbar/NewTabButton.java",
-  "java/src/org/chromium/chrome/browser/toolbar/NewTabPageDelegate.java",
   "java/src/org/chromium/chrome/browser/toolbar/ProgressAnimationSmooth.java",
   "java/src/org/chromium/chrome/browser/toolbar/SettableThemeColorProvider.java",
   "java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
index 0dc0b2b..4dd07a7e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
@@ -63,6 +63,7 @@
 import org.chromium.chrome.browser.toolbar.top.ToolbarActionModeCallback;
 import org.chromium.chrome.browser.toolbar.top.ToolbarLayout;
 import org.chromium.chrome.browser.toolbar.top.ToolbarPhone;
+import org.chromium.chrome.browser.ui.native_page.NativePage;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.components.browser_ui.widget.TintedDrawable;
 import org.chromium.components.page_info.PageInfoController;
@@ -872,6 +873,12 @@
                 @OmniboxFocusReason int reason) {}
 
         @Override
+        public boolean isCurrentPage(NativePage nativePage) {
+            return false;
+        }
+
+        @Nullable
+        @Override
         public VoiceRecognitionHandler getVoiceRecognitionHandler() {
             return null;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
index b7752eed..77ec9a2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
@@ -6,7 +6,9 @@
 
 import android.content.Context;
 import android.graphics.Rect;
+import android.net.Uri;
 
+import androidx.annotation.IntDef;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.supplier.DestroyableObservableSupplier;
@@ -30,11 +32,14 @@
 import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.ui.native_page.NativePage;
-import org.chromium.chrome.browser.ui.native_page.NativePage.NativePageType;
 import org.chromium.chrome.browser.ui.native_page.NativePageHost;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.content_public.browser.LoadUrlParams;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Creates NativePage objects to show chrome-native:// URLs using the native Android view system.
  */
@@ -118,6 +123,53 @@
         }
     }
 
+    @IntDef({NativePageType.NONE, NativePageType.CANDIDATE, NativePageType.NTP,
+            NativePageType.BOOKMARKS, NativePageType.RECENT_TABS, NativePageType.DOWNLOADS,
+            NativePageType.HISTORY, NativePageType.EXPLORE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface NativePageType {
+        int NONE = 0;
+        int CANDIDATE = 1;
+        int NTP = 2;
+        int BOOKMARKS = 3;
+        int RECENT_TABS = 4;
+        int DOWNLOADS = 5;
+        int HISTORY = 6;
+        int EXPLORE = 7;
+    }
+
+    private static @NativePageType int nativePageType(
+            String url, NativePage candidatePage, boolean isIncognito) {
+        if (url == null) return NativePageType.NONE;
+
+        Uri uri = Uri.parse(url);
+        if (!UrlConstants.CHROME_NATIVE_SCHEME.equals(uri.getScheme())
+                && !UrlConstants.CHROME_SCHEME.equals(uri.getScheme())) {
+            return NativePageType.NONE;
+        }
+
+        String host = uri.getHost();
+        if (candidatePage != null && candidatePage.getHost().equals(host)) {
+            return NativePageType.CANDIDATE;
+        }
+
+        if (UrlConstants.NTP_HOST.equals(host)) {
+            return NativePageType.NTP;
+        } else if (UrlConstants.BOOKMARKS_HOST.equals(host)) {
+            return NativePageType.BOOKMARKS;
+        } else if (UrlConstants.DOWNLOADS_HOST.equals(host)) {
+            return NativePageType.DOWNLOADS;
+        } else if (UrlConstants.HISTORY_HOST.equals(host)) {
+            return NativePageType.HISTORY;
+        } else if (UrlConstants.RECENT_TABS_HOST.equals(host) && !isIncognito) {
+            return NativePageType.RECENT_TABS;
+        } else if (ExploreSitesPage.isExploreSitesHost(host)) {
+            return NativePageType.EXPLORE;
+        } else {
+            return NativePageType.NONE;
+        }
+    }
+
     /**
      * Returns a NativePage for displaying the given URL if the URL is a valid chrome-native URL,
      * or null otherwise. If candidatePage is non-null and corresponds to the URL, it will be
@@ -137,7 +189,7 @@
             String url, NativePage candidatePage, Tab tab, boolean isIncognito) {
         NativePage page;
 
-        switch (NativePage.nativePageType(url, candidatePage, isIncognito)) {
+        switch (nativePageType(url, candidatePage, isIncognito)) {
             case NativePageType.NONE:
                 return null;
             case NativePageType.CANDIDATE:
@@ -171,14 +223,14 @@
 
     /**
      * Returns whether the URL would navigate to a native page.
-     * TODO(crbug.com/1127732): Use NativePage.isNativePageUrl directly.
+     *
      * @param url The URL to be checked.
      * @param isIncognito Whether the page will be displayed in incognito mode.
      * @return Whether the host and the scheme of the passed in URL matches one of the supported
      *         native pages.
      */
     public static boolean isNativePageUrl(String url, boolean isIncognito) {
-        return NativePage.isNativePageUrl(url, isIncognito);
+        return nativePageType(url, null, isIncognito) != NativePageType.NONE;
     }
 
     @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/FakeboxDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/FakeboxDelegate.java
index b11e4b6a..0ef3cc8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/FakeboxDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/FakeboxDelegate.java
@@ -9,6 +9,7 @@
 import org.chromium.chrome.browser.omnibox.OmniboxFocusReason;
 import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener;
 import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler;
+import org.chromium.chrome.browser.ui.native_page.NativePage;
 
 import java.util.List;
 
@@ -42,9 +43,11 @@
     boolean isUrlBarFocused();
 
     /**
-     * Get the {@link VoiceRecognitionHandler}.
-     * @return the {@link VoiceRecognitionHandler}
+     * @return whether the provided native page is the one currently displayed to the user.
      */
+    boolean isCurrentPage(NativePage nativePage);
+
+    /** Gets the {@link VoiceRecognitionHandler}. */
     @Nullable
     VoiceRecognitionHandler getVoiceRecognitionHandler();
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
index 5d149db..adc32d67 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -200,13 +200,7 @@
         public boolean isCurrentPage() {
             if (mIsDestroyed) return false;
             if (mFakeboxDelegate == null) return false;
-            return getNewTabPageForCurrentTab() == NewTabPage.this;
-        }
-
-        private NewTabPage getNewTabPageForCurrentTab() {
-            Tab currentTab = mActivityTabProvider.get();
-            NativePage nativePage = currentTab != null ? currentTab.getNativePage() : null;
-            return (nativePage instanceof NewTabPage) ? (NewTabPage) nativePage : null;
+            return mFakeboxDelegate.isCurrentPage(NewTabPage.this);
         }
 
         @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
index 64ad69a..fcf8c02 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
@@ -22,6 +22,7 @@
 import org.chromium.chrome.browser.tabmodel.IncognitoStateProvider;
 import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
 import org.chromium.chrome.browser.toolbar.top.ToolbarActionModeCallback;
+import org.chromium.chrome.browser.ui.native_page.NativePage;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 
@@ -234,6 +235,11 @@
         return mLocationBarLayout.isUrlBarFocused();
     }
 
+    @Override
+    public boolean isCurrentPage(NativePage nativePage) {
+        return mLocationBarLayout.isCurrentPage(nativePage);
+    }
+
     @Nullable
     @Override
     public VoiceRecognitionHandler getVoiceRecognitionHandler() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index e6809c3..d36750e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -73,6 +73,7 @@
 import org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil;
 import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
 import org.chromium.chrome.browser.toolbar.top.ToolbarActionModeCallback;
+import org.chromium.chrome.browser.ui.native_page.NativePage;
 import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
 import org.chromium.chrome.browser.util.KeyNavigationUtil;
 import org.chromium.components.browser_ui.styles.ChromeColors;
@@ -674,6 +675,12 @@
     }
 
     @Override
+    public boolean isCurrentPage(NativePage nativePage) {
+        assert nativePage != null;
+        return nativePage == mToolbarDataProvider.getNewTabPageForCurrentTab();
+    }
+
+    @Override
     public VoiceRecognitionHandler getVoiceRecognitionHandler() {
         return mVoiceRecognitionHandler;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
index 7c4722d..58641f03 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
@@ -269,7 +269,7 @@
         }
 
         // On non-NTP pages, there will always be an icon when unfocused.
-        if (!mToolbarDataProvider.getNewTabPageDelegate().isCurrentlyVisible()) return 0;
+        if (mToolbarDataProvider.getNewTabPageForCurrentTab() == null) return 0;
 
         // This offset is only required when the focus animation is running.
         if (!hasFocus) return 0;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
index 88ddd15..4b62c4b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
@@ -16,6 +16,7 @@
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.download.DownloadUtils;
+import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.top.ToolbarTablet;
 import org.chromium.components.browser_ui.widget.animation.CancelAwareAnimatorListener;
@@ -149,7 +150,7 @@
             mUrlFocusChangeAnimator = null;
         }
 
-        if (getToolbarDataProvider().getNewTabPageDelegate().isCurrentlyVisible()) {
+        if (getToolbarDataProvider().getNewTabPageForCurrentTab() == null) {
             finishUrlFocusChange(hasFocus);
             return;
         }
@@ -185,8 +186,9 @@
     @Override
     public void setUrlFocusChangeFraction(float fraction) {
         super.setUrlFocusChangeFraction(fraction);
-        getToolbarDataProvider().getNewTabPageDelegate().setUrlFocusChangeAnimationPercent(
-                fraction);
+
+        NewTabPage ntp = getToolbarDataProvider().getNewTabPageForCurrentTab();
+        if (ntp != null) ntp.setUrlFocusChangeAnimationPercent(fraction);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java
index 9f1634ce..63026665 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java
@@ -10,10 +10,10 @@
 import androidx.annotation.ColorRes;
 
 import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.omnibox.UrlBarData;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.toolbar.NewTabPageDelegate;
 import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.components.security_state.ConnectionSecurityLevel;
@@ -90,8 +90,8 @@
     }
 
     @Override
-    public NewTabPageDelegate getNewTabPageDelegate() {
-        return NewTabPageDelegate.EMPTY;
+    public NewTabPage getNewTabPageForCurrentTab() {
+        return null;
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandler.java
index beb83f2..8d0dc876 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandler.java
@@ -125,6 +125,7 @@
      *         animating.
      */
     private boolean showScrimAfterAnimationCompletes() {
-        return mToolbarDataProvider.getNewTabPageDelegate().isLocationBarShown();
+        if (mToolbarDataProvider.getNewTabPageForCurrentTab() == null) return false;
+        return mToolbarDataProvider.getNewTabPageForCurrentTab().isLocationBarShownInNTP();
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
index 2a032a4..9ce05a9a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
@@ -20,6 +20,8 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
 import org.chromium.chrome.browser.dom_distiller.DomDistillerTabUtils;
+import org.chromium.chrome.browser.native_page.NativePageFactory;
+import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.omnibox.ChromeAutocompleteSchemeClassifier;
 import org.chromium.chrome.browser.omnibox.SearchEngineLogoUtils;
@@ -29,7 +31,6 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TrustedCdn;
-import org.chromium.chrome.browser.ui.native_page.NativePage;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
 import org.chromium.components.embedder_support.util.UrlConstants;
@@ -48,9 +49,8 @@
 /**
  * Provides a way of accessing toolbar data and state.
  */
-public class LocationBarModel implements ToolbarDataProvider {
+public class LocationBarModel implements ToolbarDataProvider, ToolbarCommonPropertiesModel {
     private final Context mContext;
-    private final NewTabPageDelegate mNtpDelegate;
 
     private Tab mTab;
     private int mPrimaryColor;
@@ -66,9 +66,8 @@
      * Default constructor for this class.
      * @param context The Context used for styling the toolbar visuals.
      */
-    public LocationBarModel(Context context, NewTabPageDelegate newTabPageDelegate) {
+    public LocationBarModel(Context context) {
         mContext = context;
-        mNtpDelegate = newTabPageDelegate;
         mPrimaryColor = ChromeColors.getDefaultThemeColor(context.getResources(), false);
     }
 
@@ -139,8 +138,11 @@
     }
 
     @Override
-    public NewTabPageDelegate getNewTabPageDelegate() {
-        return mNtpDelegate;
+    public NewTabPage getNewTabPageForCurrentTab() {
+        if (hasTab() && mTab.getNativePage() instanceof NewTabPage) {
+            return (NewTabPage) mTab.getNativePage();
+        }
+        return null;
     }
 
     @Override
@@ -148,7 +150,7 @@
         if (!hasTab()) return UrlBarData.EMPTY;
 
         String url = getCurrentUrl();
-        if (NativePage.isNativePageUrl(url, isIncognito()) || UrlUtilities.isNTPUrl(url)) {
+        if (NativePageFactory.isNativePageUrl(url, isIncognito()) || UrlUtilities.isNTPUrl(url)) {
             return UrlBarData.EMPTY;
         }
 
@@ -419,7 +421,7 @@
 
         boolean skipIconForNeutralState =
                 !SearchEngineLogoUtils.shouldShowSearchEngineLogo(isIncognito())
-                || mNtpDelegate.isCurrentlyVisible();
+                || getNewTabPageForCurrentTab() != null;
 
         return SecurityStatusIcon.getSecurityIconResource(securityLevel,
                 SecurityStateModel.shouldShowDangerTriangleForWarningLevel(), isSmallDevice,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/NewTabPageDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/NewTabPageDelegate.java
deleted file mode 100644
index aff1e163..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/NewTabPageDelegate.java
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.toolbar;
-
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.view.MotionEvent;
-import android.view.View;
-
-import androidx.annotation.Nullable;
-
-import org.chromium.base.Callback;
-
-/**
- * Delegate that provides the toolbar with the info of the NTP for the current tab.
- * TODO(crbug.com/1127732): Consider moving this out of toolbar/ into
- *     its own target for omnibox as well.
- */
-public interface NewTabPageDelegate {
-    /**
-     * @return {@code true} if the NewTabPage is currently visible.
-     */
-    default boolean isCurrentlyVisible() {
-        return false;
-    }
-
-    /**
-     * @return Whether the location bar is shown in the NTP.
-     */
-    default boolean isLocationBarShown() {
-        return false;
-    }
-
-    /**
-     * @return {@code true} if we're transitioning away from showing the location bar.
-     */
-    default boolean transitioningAwayFromLocationBar() {
-        return false;
-    }
-
-    /**
-     * Set the listener for NTP to handle the scroll event.
-     * @param scrollCallback Callback to be invoked when the event occurs.
-     */
-    default void setSearchBoxScrollListener(@Nullable Callback<Float> scrollCallback) {}
-
-    /**
-     * Get the bounds of the search box in relation to the top level NewTabPage view.
-     *
-     * @param bounds The current drawing location of the search box.
-     * @param translation The translation applied to the search box by the parent view hierarchy up
-     *                    to the NewTabPage view.
-     */
-    default void getSearchBoxBounds(Rect bounds, Point translation) {}
-
-    /**
-     * Updates the opacity of the search box when scrolling.
-     *
-     * @param alpha opacity (alpha) value to use.
-     */
-    default void setSearchBoxAlpha(float alpha) {}
-
-    /**
-     * Updates the opacity of the search provider logo when scrolling.
-     *
-     * @param alpha opacity (alpha) value to use.
-     */
-    default void setSearchProviderLogoAlpha(float alpha) {}
-
-    /**
-     * Set the search box background drawable.
-     *
-     * @param drawable The search box background.
-     */
-    default void setSearchBoxBackground(Drawable drawable) {}
-
-    /**
-     * Specifies the percentage the URL is focused during an animation.  1.0 specifies that the URL
-     * bar has focus and has completed the focus animation.  0 is when the URL bar is does not have
-     * any focus.
-     *
-     * @param percent The percentage of the URL bar focus animation.
-     */
-    default void setUrlFocusChangeAnimationPercent(float fraction) {}
-
-    /**
-     * Pass the motion event to NewTabPage object.
-     *
-     * @see {@link View#dispatchTouchEvent(MotionEvent)}
-     */
-    default boolean dispatchTouchEvent(MotionEvent ev) {
-        return false;
-    }
-
-    /**
-     * Empty implementation of NewTabDelegate. Used for a default before initialization.
-     */
-    public static final NewTabPageDelegate EMPTY = new NewTabPageDelegate() {};
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarCommonPropertiesModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarCommonPropertiesModel.java
index eb710e6..1134f02 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarCommonPropertiesModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarCommonPropertiesModel.java
@@ -7,6 +7,8 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import org.chromium.chrome.browser.ntp.NewTabPage;
+
 /**
  * Defines an interface that provides common properties to toolbar and omnibox classes.
  */
@@ -18,10 +20,9 @@
     String getCurrentUrl();
 
     /**
-     * @return a delegate providing the info for the NTP of the current tab.
+     * @return The NewTabPage shown for the current Tab or null if one is not being shown.
      */
-    @NonNull
-    NewTabPageDelegate getNewTabPageDelegate();
+    NewTabPage getNewTabPageForCurrentTab();
 
     /**
      * @return Whether the toolbar is currently being displayed for incognito.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java
index aca67d4..f374078d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java
@@ -12,6 +12,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 
+import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.omnibox.UrlBarData;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
@@ -49,6 +50,12 @@
     String getCurrentUrl();
 
     /**
+     * @return The NewTabPage shown for the current Tab or null if one is not being shown.
+     */
+    @Override
+    NewTabPage getNewTabPageForCurrentTab();
+
+    /**
      * @return Whether the toolbar is currently being displayed for incognito.
      */
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index da09635..f9e5aa5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -7,12 +7,9 @@
 import android.content.ComponentCallbacks;
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
-import android.graphics.Point;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.text.TextUtils;
-import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnAttachStateChangeListener;
 import android.view.View.OnClickListener;
@@ -59,8 +56,8 @@
 import org.chromium.chrome.browser.ntp.IncognitoNewTabPage;
 import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.omnibox.LocationBar;
-import org.chromium.chrome.browser.omnibox.LocationBarCoordinator;
 import org.chromium.chrome.browser.omnibox.OmniboxFocusReason;
+import org.chromium.chrome.browser.omnibox.LocationBarCoordinator;
 import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener;
 import org.chromium.chrome.browser.previews.Previews;
 import org.chromium.chrome.browser.previews.PreviewsAndroidBridge;
@@ -91,7 +88,6 @@
 import org.chromium.chrome.browser.toolbar.top.ToolbarControlContainer;
 import org.chromium.chrome.browser.toolbar.top.ToolbarLayout;
 import org.chromium.chrome.browser.toolbar.top.ToolbarPhone;
-import org.chromium.chrome.browser.toolbar.top.ToolbarTablet;
 import org.chromium.chrome.browser.toolbar.top.TopToolbarCoordinator;
 import org.chromium.chrome.browser.toolbar.top.ViewShiftingActionBarDelegate;
 import org.chromium.chrome.browser.ui.TabObscuringHandler;
@@ -265,9 +261,7 @@
         mTabModelSelectorSupplier = tabModelSelectorSupplier;
         mOmniboxFocusStateSupplier = omniboxFocusStateSupplier;
 
-        ToolbarLayout toolbarLayout = mActivity.findViewById(R.id.toolbar);
-        NewTabPageDelegate ntpDelegate = createNewTabPageDelegate(toolbarLayout);
-        mLocationBarModel = new LocationBarModel(activity, ntpDelegate);
+        mLocationBarModel = new LocationBarModel(activity);
         mControlContainer = controlContainer;
         assert mControlContainer != null;
 
@@ -323,6 +317,7 @@
         ThemeColorProvider browsingModeThemeColorProvider =
                 mActivity.isTablet() ? mAppThemeColorProvider : mTabThemeColorProvider;
         ThemeColorProvider overviewModeThemeColorProvider = mAppThemeColorProvider;
+        ToolbarLayout toolbarLayout = mActivity.findViewById(R.id.toolbar);
 
         mMenuButtonCoordinator = new MenuButtonCoordinator(appMenuCoordinatorSupplier,
                 mControlsVisibilityDelegate, mActivity,
@@ -388,7 +383,7 @@
                 if (tab == null) return;
 
                 refreshSelectedTab(tab);
-                onTabOrModelChanged();
+                mToolbar.onTabOrModelChanged();
             }
 
             @Override
@@ -444,7 +439,7 @@
             @Override
             public void onContentChanged(Tab tab) {
                 if (tab.isNativePage()) TabThemeColorHelper.get(tab).updateIfNeeded(false);
-                notifyTabLoadingNtp();
+                mToolbar.onTabContentViewChanged();
                 if (shouldShowCursorInLocationBar()) {
                     mLocationBar.showUrlBarCursorWithoutFocusAnimations();
                 }
@@ -460,12 +455,12 @@
 
             @Override
             public void onLoadUrl(Tab tab, LoadUrlParams params, int loadType) {
-                NewTabPage ntp = getNewTabPageForCurrentTab();
+                NewTabPage ntp = mLocationBarModel.getNewTabPageForCurrentTab();
                 if (ntp == null) return;
                 if (!UrlUtilities.isNTPUrl(params.getUrl())
                         && loadType != TabLoadStatus.PAGE_LOAD_FAILED) {
                     ntp.setUrlFocusAnimationsDisabled(true);
-                    onTabOrModelChanged();
+                    mToolbar.onTabOrModelChanged();
                 }
             }
 
@@ -518,11 +513,11 @@
                 // location bar animations.
                 if (navigation.errorCode() != NetError.OK && navigation.isInMainFrame()
                         && !hasPendingNonNtpNavigation(tab)) {
-                    NewTabPage ntp = getNewTabPageForCurrentTab();
+                    NewTabPage ntp = mLocationBarModel.getNewTabPageForCurrentTab();
                     if (ntp == null) return;
 
                     ntp.setUrlFocusAnimationsDisabled(false);
-                    onTabOrModelChanged();
+                    mToolbar.onTabOrModelChanged();
                 }
             }
 
@@ -662,7 +657,6 @@
             MenuButtonCoordinator startSurfaceMenuButtonCoordinator, Invalidator invalidator,
             IdentityDiscController identityDiscController,
             OneshotSupplier<StartSurface> startSurfaceSupplier) {
-        // clang-format off
         TopToolbarCoordinator toolbar = new TopToolbarCoordinator(controlContainer, toolbarLayout,
                 mLocationBarModel, mToolbarTabController,
                 new UserEducationHelper(mActivity, mHandler, TrackerFactory::getTrackerForProfile),
@@ -670,16 +664,17 @@
                 mAppThemeColorProvider, mMenuButtonCoordinator, startSurfaceMenuButtonCoordinator,
                 mMenuButtonCoordinator.getMenuButtonHelperSupplier(), mTabModelSelectorSupplier,
                 mHomeButtonVisibilitySupplier, mIdentityDiscStateSupplier,
-                (client) -> {
+                (client)
+                        -> {
                     if (invalidator != null) {
                         invalidator.invalidate(client);
                     } else {
                         client.run();
                     }
                 },
-                () -> identityDiscController.getForStartSurface(mStartSurfaceState),
+                ()
+                        -> identityDiscController.getForStartSurface(mStartSurfaceState),
                 startSurfaceSupplier);
-        // clang-format on
         mHomepageStateListener =
                 () -> mHomeButtonVisibilitySupplier.set(HomepageManager.isHomepageEnabled());
         HomepageManager.getInstance().addListener(mHomepageStateListener);
@@ -688,7 +683,7 @@
             identityDiscController.addObserver(
                     (canShowHint) -> mIdentityDiscStateSupplier.set(canShowHint));
         }
-        HomeButton homeButton = toolbarLayout.getHomeButton();
+        HomeButton homeButton = mActivity.findViewById(R.id.home_button);
         if (homeButton != null) {
             homeButton.init(mHomeButtonVisibilitySupplier,
                     HomepageManager.getInstance()::onMenuClick,
@@ -697,119 +692,6 @@
         return toolbar;
     }
 
-    // Base abstract implementation of NewTabPageDelegate for phone/table toolbar layout.
-    private abstract class ToolbarNtpDelegate implements NewTabPageDelegate {
-        protected NewTabPage mVisibleNtp;
-
-        @Override
-        public boolean isCurrentlyVisible() {
-            return mVisibleNtp != null;
-        }
-
-        @Override
-        public boolean dispatchTouchEvent(MotionEvent ev) {
-            assert mVisibleNtp != null;
-            // No null check -- the toolbar should not be moved if we are not on an NTP.
-            return mVisibleNtp.getView().dispatchTouchEvent(ev);
-        }
-
-        @Override
-        public boolean isLocationBarShown() {
-            NewTabPage ntp = getNewTabPageForCurrentTab();
-            return ntp != null && ntp.isLocationBarShownInNTP();
-        }
-
-        @Override
-        public boolean transitioningAwayFromLocationBar() {
-            return isCurrentlyVisible() && mVisibleNtp.isLocationBarShownInNTP()
-                    && !isLocationBarShown();
-        }
-
-        @Override
-        public void setSearchBoxScrollListener(Callback<Float> scrollCallback) {
-            NewTabPage newVisibleNtp = getNewTabPageForCurrentTab();
-            if (mVisibleNtp == newVisibleNtp) return;
-            if (mVisibleNtp != null) mVisibleNtp.setSearchBoxScrollListener(null);
-            mVisibleNtp = newVisibleNtp;
-            if (mVisibleNtp != null && shouldUpdateListener()) {
-                mVisibleNtp.setSearchBoxScrollListener(
-                        (fraction) -> scrollCallback.onResult(fraction));
-            }
-        }
-
-        // Boolean predicate that tells if the NewTabPage.OnSearchBoxScrollListener
-        // should be updated or not
-        protected abstract boolean shouldUpdateListener();
-
-        @Override
-        public void getSearchBoxBounds(Rect bounds, Point translation) {
-            assert getNewTabPageForCurrentTab() != null;
-            getNewTabPageForCurrentTab().getSearchBoxBounds(bounds, translation);
-        }
-
-        @Override
-        public void setSearchBoxBackground(Drawable drawable) {
-            assert getNewTabPageForCurrentTab() != null;
-            getNewTabPageForCurrentTab().setSearchBoxBackground(drawable);
-        }
-
-        @Override
-        public void setSearchBoxAlpha(float alpha) {
-            assert getNewTabPageForCurrentTab() != null;
-            getNewTabPageForCurrentTab().setSearchBoxAlpha(alpha);
-        }
-
-        @Override
-        public void setSearchProviderLogoAlpha(float alpha) {
-            assert getNewTabPageForCurrentTab() != null;
-            getNewTabPageForCurrentTab().setSearchProviderLogoAlpha(alpha);
-        }
-
-        @Override
-        public void setUrlFocusChangeAnimationPercent(float fraction) {
-            NewTabPage ntp = getNewTabPageForCurrentTab();
-            if (ntp != null) ntp.setUrlFocusChangeAnimationPercent(fraction);
-        }
-    }
-
-    private NewTabPageDelegate createNewTabPageDelegate(ToolbarLayout toolbarLayout) {
-        if (toolbarLayout instanceof ToolbarPhone) {
-            return new ToolbarNtpDelegate() {
-                @Override
-                protected boolean shouldUpdateListener() {
-                    return mVisibleNtp.isLocationBarShownInNTP();
-                }
-            };
-        } else if (toolbarLayout instanceof ToolbarTablet) {
-            return new ToolbarNtpDelegate() {
-                @Override
-                protected boolean shouldUpdateListener() {
-                    return true;
-                }
-            };
-        }
-        return NewTabPageDelegate.EMPTY;
-    }
-
-    private void onTabOrModelChanged() {
-        notifyTabLoadingNtp();
-        mLocationBar.updateMicButtonState();
-        mToolbar.onTabOrModelChanged();
-    }
-
-    private void notifyTabLoadingNtp() {
-        NewTabPage ntp = getNewTabPageForCurrentTab();
-        if (ntp != null) mLocationBar.onTabLoadingNTP(ntp);
-    }
-
-    private NewTabPage getNewTabPageForCurrentTab() {
-        if (mLocationBarModel.hasTab()) {
-            NativePage nativePage = mLocationBarModel.getTab().getNativePage();
-            if (nativePage instanceof NewTabPage) return (NewTabPage) nativePage;
-        }
-        return null;
-    }
-
     /**
      * Called when the contextual action bar's visibility has changed (i.e. the widget shown
      * when you can copy/paste text after long press).
@@ -1398,7 +1280,7 @@
                     tab != null ? TabThemeColorHelper.getColor(tab) : defaultPrimaryColor;
             onThemeColorChanged(primaryColor, false);
 
-            onTabOrModelChanged();
+            mToolbar.onTabOrModelChanged();
 
             if (tab != null) {
                 mToolbar.onNavigatedToDifferentPage();
@@ -1506,7 +1388,7 @@
      */
     @VisibleForTesting
     public HomeButton getHomeButtonForTesting() {
-        return mToolbar.getToolbarLayoutForTesting().getHomeButton();
+        return mToolbar.getToolbarLayoutForTesting().getHomeButtonForTesting();
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressMediator.java
index b634150..5ccf5340 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressMediator.java
@@ -6,10 +6,10 @@
 
 import org.chromium.base.MathUtils;
 import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.chrome.browser.native_page.NativePageFactory;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.load_progress.LoadProgressProperties.CompletionState;
-import org.chromium.chrome.browser.ui.native_page.NativePage;
 import org.chromium.chrome.features.start_surface.StartSurfaceConfiguration;
 import org.chromium.components.embedder_support.util.UrlUtilities;
 import org.chromium.content_public.browser.NavigationHandle;
@@ -38,7 +38,8 @@
                     return;
                 }
 
-                if (NativePage.isNativePageUrl(navigation.getUrlString(), tab.isIncognito())) {
+                if (NativePageFactory.isNativePageUrl(
+                            navigation.getUrlString(), tab.isIncognito())) {
                     finishLoadProgress(false);
                     return;
                 }
@@ -63,7 +64,8 @@
             @Override
             public void onLoadProgressChanged(Tab tab, float progress) {
                 if (UrlUtilities.isNTPUrl(tab.getUrlString())
-                        || NativePage.isNativePageUrl(tab.getUrlString(), tab.isIncognito())) {
+                        || NativePageFactory.isNativePageUrl(
+                                tab.getUrlString(), tab.isIncognito())) {
                     return;
                 }
 
@@ -120,7 +122,7 @@
         }
 
         if (tab.isLoading()) {
-            if (NativePage.isNativePageUrl(tab.getUrlString(), tab.isIncognito())) {
+            if (NativePageFactory.isNativePageUrl(tab.getUrlString(), tab.isIncognito())) {
                 finishLoadProgress(false);
             } else {
                 startLoadProgress();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
index db66f581..674e2be 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
@@ -30,16 +30,16 @@
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
 import org.chromium.chrome.browser.compositor.overlays.toolbar.TopToolbarOverlayCoordinator;
 import org.chromium.chrome.browser.findinpage.FindToolbar;
+import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.omnibox.LocationBar;
-import org.chromium.chrome.browser.omnibox.LocationBarCoordinator;
 import org.chromium.chrome.browser.omnibox.OmniboxFocusReason;
+import org.chromium.chrome.browser.omnibox.LocationBarCoordinator;
 import org.chromium.chrome.browser.omnibox.UrlBarData;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.toolbar.ButtonData;
 import org.chromium.chrome.browser.toolbar.HomeButton;
-import org.chromium.chrome.browser.toolbar.NewTabPageDelegate;
 import org.chromium.chrome.browser.toolbar.TabCountProvider;
 import org.chromium.chrome.browser.toolbar.ThemeColorProvider;
 import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver;
@@ -278,8 +278,8 @@
             }
 
             @Override
-            public NewTabPageDelegate getNewTabPageDelegate() {
-                return NewTabPageDelegate.EMPTY;
+            public NewTabPage getNewTabPageForCurrentTab() {
+                return null;
             }
 
             @Override
@@ -556,7 +556,14 @@
      * tabs but no normal tabs will still allow you to select the normal model), this should
      * not guarantee that the model's current tab is non-null.
      */
-    void onTabOrModelChanged() {}
+    void onTabOrModelChanged() {
+        NewTabPage ntp = getToolbarDataProvider().getNewTabPageForCurrentTab();
+        if (ntp != null) {
+            getLocationBar().onTabLoadingNTP(ntp);
+        }
+
+        getLocationBar().updateMicButtonState();
+    }
 
     /**
      * For extending classes to override and carry out the changes related with the primary color
@@ -604,7 +611,10 @@
     /**
      * Triggered when the content view for the specified tab has changed.
      */
-    void onTabContentViewChanged() {}
+    void onTabContentViewChanged() {
+        NewTabPage ntp = getToolbarDataProvider().getNewTabPageForCurrentTab();
+        if (ntp != null) getLocationBar().onTabLoadingNTP(ntp);
+    }
 
     boolean isReadyForTextureCapture() {
         return true;
@@ -850,7 +860,8 @@
     /**
      * @return {@link HomeButton} this {@link ToolbarLayout} contains.
      */
-    public HomeButton getHomeButton() {
+    @VisibleForTesting
+    public HomeButton getHomeButtonForTesting() {
         return null;
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
index 3a1940a..ec05243 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -52,6 +52,7 @@
 import org.chromium.chrome.browser.device.DeviceClassManager;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.homepage.HomepageManager;
+import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.omnibox.LocationBar;
 import org.chromium.chrome.browser.omnibox.LocationBarCoordinator;
 import org.chromium.chrome.browser.omnibox.SearchEngineLogoUtils;
@@ -62,7 +63,6 @@
 import org.chromium.chrome.browser.toolbar.ButtonData;
 import org.chromium.chrome.browser.toolbar.HomeButton;
 import org.chromium.chrome.browser.toolbar.KeyboardNavigationListener;
-import org.chromium.chrome.browser.toolbar.NewTabPageDelegate;
 import org.chromium.chrome.browser.toolbar.TabCountProvider;
 import org.chromium.chrome.browser.toolbar.TabCountProvider.TabCountObserver;
 import org.chromium.chrome.browser.toolbar.TabSwitcherDrawable;
@@ -87,7 +87,8 @@
 /**
  * Phone specific toolbar implementation.
  */
-public class ToolbarPhone extends ToolbarLayout implements OnClickListener, TabCountObserver {
+public class ToolbarPhone extends ToolbarLayout
+        implements OnClickListener, NewTabPage.OnSearchBoxScrollListener, TabCountObserver {
     /** The amount of time transitioning from one theme color to another should take in ms. */
     public static final long THEME_COLOR_TRANSITION_DURATION = 250;
 
@@ -254,6 +255,7 @@
 
     protected @VisualState int mVisualState = VisualState.NORMAL;
 
+    private NewTabPage mVisibleNewTabPage;
     private float mPreTextureCaptureAlpha = 1f;
     private int mPreTextureCaptureVisibility;
     private boolean mIsOverlayTabStackDrawableLight;
@@ -499,7 +501,10 @@
         // reached the top of the page yet.
         if (mNtpSearchBoxTranslation.y < 0
                 && mLocationBar.getPhoneCoordinator().getTranslationY() > 0) {
-            return getToolbarDataProvider().getNewTabPageDelegate().dispatchTouchEvent(ev);
+            NewTabPage newTabPage = getToolbarDataProvider().getNewTabPageForCurrentTab();
+
+            // No null check -- the toolbar should not be moved if we are not on an NTP.
+            return newTabPage.getView().dispatchTouchEvent(ev);
         }
 
         return super.onTouchEvent(ev);
@@ -778,7 +783,9 @@
         return super.verifyDrawable(who) || who == mActiveLocationBarBackground;
     }
 
-    private void onNtpScrollChanged(float scrollFraction) {
+    // NewTabPage.OnSearchBoxScrollListener
+    @Override
+    public void onNtpScrollChanged(float scrollFraction) {
         mNtpSearchBoxScrollFraction = scrollFraction;
         updateUrlExpansionFraction();
         updateUrlExpansionAnimation();
@@ -1000,8 +1007,11 @@
 
         Tab currentTab = getToolbarDataProvider().getTab();
         if (currentTab != null) {
-            getToolbarDataProvider().getNewTabPageDelegate().setUrlFocusChangeAnimationPercent(
-                    mUrlFocusChangeFraction);
+            NewTabPage ntp = getToolbarDataProvider().getNewTabPageForCurrentTab();
+            if (ntp != null) {
+                ntp.setUrlFocusChangeAnimationPercent(mUrlFocusChangeFraction);
+            }
+
             if (isLocationBarShownInNTP()
                     && !getToolbarDataProvider().isInOverviewAndShowingOmnibox()) {
                 updateNtpTransitionAnimation();
@@ -1138,8 +1148,8 @@
             mToolbarShadow.setAlpha(alpha);
         }
 
-        NewTabPageDelegate ntpDelegate = getToolbarDataProvider().getNewTabPageDelegate();
-        ntpDelegate.getSearchBoxBounds(mNtpSearchBoxBounds, mNtpSearchBoxTranslation);
+        NewTabPage ntp = getToolbarDataProvider().getNewTabPageForCurrentTab();
+        ntp.getSearchBoxBounds(mNtpSearchBoxBounds, mNtpSearchBoxTranslation);
         int locationBarTranslationY = Math.max(
                 0, (mNtpSearchBoxBounds.top - mLocationBar.getPhoneCoordinator().getTop()));
         mLocationBar.getPhoneCoordinator().setTranslationY(locationBarTranslationY);
@@ -1172,7 +1182,7 @@
         mLocationBar.getPhoneCoordinator().setAlpha(relativeAlpha);
 
         // The search box on the NTP is visible if our omnibox is invisible, and vice-versa.
-        ntpDelegate.setSearchBoxAlpha(1f - relativeAlpha);
+        ntp.setSearchBoxAlpha(1f - relativeAlpha);
         if (!mForceDrawLocationBarBackground) {
             if (mActiveLocationBarBackground instanceof NtpSearchBoxDrawable) {
                 ((NtpSearchBoxDrawable) mActiveLocationBarBackground).resetBoundsToLastNonToolbar();
@@ -1634,7 +1644,7 @@
     }
 
     @Override
-    public HomeButton getHomeButton() {
+    public HomeButton getHomeButtonForTesting() {
         return mHomeButton;
     }
 
@@ -2255,18 +2265,22 @@
     }
 
     private void updateNtpAnimationState() {
-        NewTabPageDelegate ntpDelegate = getToolbarDataProvider().getNewTabPageDelegate();
-
         // Store previous NTP scroll before calling reset as that clears this value.
-        boolean wasShowingNtp = ntpDelegate.isCurrentlyVisible();
+        boolean wasShowingNtp = mVisibleNewTabPage != null;
         float previousNtpScrollFraction = mNtpSearchBoxScrollFraction;
 
         resetNtpAnimationValues();
-        ntpDelegate.setSearchBoxScrollListener(this::onNtpScrollChanged);
-        if (ntpDelegate.isLocationBarShown()) {
+        if (mVisibleNewTabPage != null) {
+            mVisibleNewTabPage.setSearchBoxScrollListener(null);
+            mVisibleNewTabPage = null;
+        }
+        mVisibleNewTabPage = getToolbarDataProvider().getNewTabPageForCurrentTab();
+        if (mVisibleNewTabPage != null && mVisibleNewTabPage.isLocationBarShownInNTP()) {
+            mVisibleNewTabPage.setSearchBoxScrollListener(this);
+
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                 NtpSearchBoxDrawable ntpSearchBox = new NtpSearchBoxDrawable(getContext(), this);
-                ntpDelegate.setSearchBoxBackground(ntpSearchBox);
+                mVisibleNewTabPage.setSearchBoxBackground(ntpSearchBox);
                 mActiveLocationBarBackground = ntpSearchBox;
             }
 
@@ -2309,11 +2323,13 @@
     }
 
     private boolean isLocationBarShownInNTP() {
-        return getToolbarDataProvider().getNewTabPageDelegate().isLocationBarShown();
+        NewTabPage ntp = getToolbarDataProvider().getNewTabPageForCurrentTab();
+        return ntp != null && ntp.isLocationBarShownInNTP();
     }
 
     private boolean isLocationBarCurrentlyShown() {
-        return !isLocationBarShownInNTP() || mUrlExpansionFraction > 0;
+        NewTabPage ntp = getToolbarDataProvider().getNewTabPageForCurrentTab();
+        return ntp == null || !isLocationBarShownInNTP() || mUrlExpansionFraction > 0;
     }
 
     /**
@@ -2527,8 +2543,8 @@
             return;
         }
 
-        boolean transitioningAwayFromLocationBarInNTP =
-                getToolbarDataProvider().getNewTabPageDelegate().transitioningAwayFromLocationBar();
+        boolean transitioningAwayFromLocationBarInNTP = mVisibleNewTabPage != null
+                && mVisibleNewTabPage.isLocationBarShownInNTP() && !isLocationBarShownInNTP();
 
         if (mTabSwitcherState == STATIC_TAB && !mUrlFocusChangeInProgress && !urlHasFocus()
                 && !transitioningAwayFromLocationBarInNTP) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
index 0e312bf3..5894c2f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
@@ -30,6 +30,7 @@
 import org.chromium.chrome.browser.NavigationPopup;
 import org.chromium.chrome.browser.download.DownloadUtils;
 import org.chromium.chrome.browser.homepage.HomepageManager;
+import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.omnibox.LocationBar;
 import org.chromium.chrome.browser.omnibox.LocationBarCoordinator;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
@@ -39,7 +40,6 @@
 import org.chromium.chrome.browser.toolbar.ButtonData;
 import org.chromium.chrome.browser.toolbar.HomeButton;
 import org.chromium.chrome.browser.toolbar.KeyboardNavigationListener;
-import org.chromium.chrome.browser.toolbar.NewTabPageDelegate;
 import org.chromium.chrome.browser.toolbar.TabCountProvider;
 import org.chromium.chrome.browser.toolbar.TabCountProvider.TabCountObserver;
 import org.chromium.chrome.browser.toolbar.ToolbarColors;
@@ -92,6 +92,8 @@
     private boolean mShouldAnimateButtonVisibilityChange;
     private AnimatorSet mButtonVisibilityAnimators;
 
+    private NewTabPage mVisibleNtp;
+
     /**
      * Constructs a ToolbarTablet object.
      * @param context The Context in which this View object is created.
@@ -405,13 +407,24 @@
      * Called when the currently visible New Tab Page changes.
      */
     private void updateNtp() {
-        NewTabPageDelegate ntpDelegate = getToolbarDataProvider().getNewTabPageDelegate();
-        ntpDelegate.setSearchBoxScrollListener((scrollFraction) -> {
-            // Fade the search box out in the first 40% of the scrolling transition.
-            float alpha = Math.max(1f - scrollFraction * 2.5f, 0f);
-            ntpDelegate.setSearchBoxAlpha(alpha);
-            ntpDelegate.setSearchProviderLogoAlpha(alpha);
-        });
+        NewTabPage newVisibleNtp = getToolbarDataProvider().getNewTabPageForCurrentTab();
+        if (mVisibleNtp == newVisibleNtp) return;
+
+        if (mVisibleNtp != null) {
+            mVisibleNtp.setSearchBoxScrollListener(null);
+        }
+        mVisibleNtp = newVisibleNtp;
+        if (mVisibleNtp != null) {
+            mVisibleNtp.setSearchBoxScrollListener(new NewTabPage.OnSearchBoxScrollListener() {
+                @Override
+                public void onNtpScrollChanged(float scrollFraction) {
+                    // Fade the search box out in the first 40% of the scrolling transition.
+                    float alpha = Math.max(1f - scrollFraction * 2.5f, 0f);
+                    mVisibleNtp.setSearchBoxAlpha(alpha);
+                    mVisibleNtp.setSearchProviderLogoAlpha(alpha);
+                }
+            });
+        }
     }
 
     @Override
@@ -595,7 +608,7 @@
     }
 
     @Override
-    public HomeButton getHomeButton() {
+    public HomeButton getHomeButtonForTesting() {
         return mHomeButton;
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java
index 72d8df7..0fef330 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java
@@ -41,7 +41,6 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.LocationBarModel;
-import org.chromium.chrome.browser.toolbar.NewTabPageDelegate;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.OmniboxTestUtils;
@@ -86,7 +85,7 @@
         private Integer mSecurityLevel;
 
         public TestLocationBarModel() {
-            super(ContextUtils.getApplicationContext(), NewTabPageDelegate.EMPTY);
+            super(ContextUtils.getApplicationContext());
             initializeWithNative();
         }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java
index e5e22dd9..6ef73cdcf5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java
@@ -38,8 +38,8 @@
 import org.chromium.base.test.util.Batch;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
-import org.chromium.chrome.browser.toolbar.NewTabPageDelegate;
 import org.chromium.chrome.browser.toolbar.ToolbarCommonPropertiesModel;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
@@ -61,7 +61,7 @@
     public TestRule mProcessor = new Features.JUnitProcessor();
 
     @Mock
-    NewTabPageDelegate mNewTabPageDelegate;
+    NewTabPage mNewTabPage;
     @Mock
     ToolbarCommonPropertiesModel mToolbarCommonPropertiesModel;
     @Mock
@@ -124,8 +124,7 @@
     @UiThreadTest
     public void searchEngineLogo_showGoogleLogo_hideAfterAnimationFinished() {
         setupSearchEngineLogoForTesting(true, false, false);
-        doReturn(mNewTabPageDelegate).when(mToolbarCommonPropertiesModel).getNewTabPageDelegate();
-        doReturn(true).when(mNewTabPageDelegate).isCurrentlyVisible();
+        doReturn(mNewTabPage).when(mToolbarCommonPropertiesModel).getNewTabPageForCurrentTab();
         doReturn("chrome://newtab").when(mToolbarCommonPropertiesModel).getCurrentUrl();
 
         mMediator.updateSearchEngineStatusIcon(true, true, TEST_SEARCH_URL);
@@ -172,8 +171,7 @@
         setupSearchEngineLogoForTesting(true, false, false);
         doReturn(false).when(mToolbarCommonPropertiesModel).isLoading();
         doReturn(UrlConstants.NTP_URL).when(mToolbarCommonPropertiesModel).getCurrentUrl();
-        doReturn(mNewTabPageDelegate).when(mToolbarCommonPropertiesModel).getNewTabPageDelegate();
-        doReturn(true).when(mNewTabPageDelegate).isCurrentlyVisible();
+        doReturn(mNewTabPage).when(mToolbarCommonPropertiesModel).getNewTabPageForCurrentTab();
 
         mMediator.setUrlHasFocus(false);
         mMediator.setShowIconsWhenUrlFocused(true);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewRenderTest.java
index 5ff4e25..d569ccc9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewRenderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewRenderTest.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.omnibox.status.StatusProperties.StatusIconResource;
 import org.chromium.chrome.browser.omnibox.status.StatusView.StatusViewDelegate;
 import org.chromium.chrome.browser.toolbar.LocationBarModel;
-import org.chromium.chrome.browser.toolbar.NewTabPageDelegate;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ChromeRenderTestRule;
 import org.chromium.components.browser_ui.widget.CompositeTouchDelegate;
@@ -73,7 +72,7 @@
                                   .findViewById(org.chromium.chrome.R.id.location_bar_status);
             mStatusView.setCompositeTouchDelegate(new CompositeTouchDelegate(view));
             mStatusView.setToolbarCommonPropertiesModel(
-                    new LocationBarModel(mStatusView.getContext(), NewTabPageDelegate.EMPTY));
+                    new LocationBarModel(mStatusView.getContext()));
             mStatusModel = new PropertyModel.Builder(StatusProperties.ALL_KEYS).build();
             PropertyModelChangeProcessor.create(mStatusModel, mStatusView, new StatusViewBinder());
         });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewTest.java
index 5f05faad..675c2833 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewTest.java
@@ -36,7 +36,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.omnibox.status.StatusProperties.StatusIconResource;
 import org.chromium.chrome.browser.toolbar.LocationBarModel;
-import org.chromium.chrome.browser.toolbar.NewTabPageDelegate;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.components.browser_ui.widget.CompositeTouchDelegate;
@@ -77,7 +76,7 @@
             mStatusView.setDelegateForTesting(mStatusViewDelegate);
             mStatusView.setCompositeTouchDelegate(new CompositeTouchDelegate(view));
             mStatusView.setToolbarCommonPropertiesModel(
-                    new LocationBarModel(mStatusView.getContext(), NewTabPageDelegate.EMPTY));
+                    new LocationBarModel(mStatusView.getContext()));
             mStatusModel = new PropertyModel.Builder(StatusProperties.ALL_KEYS).build();
             mStatusMCP = PropertyModelChangeProcessor.create(
                     mStatusModel, mStatusView, new StatusViewBinder());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandlerTest.java
index 9449dde..5a8ba75 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandlerTest.java
@@ -33,6 +33,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.omnibox.UrlBarData;
 import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
 import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteController.OnSuggestionsReceivedListener;
@@ -46,7 +47,6 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.MockTab;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.toolbar.NewTabPageDelegate;
 import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
@@ -215,8 +215,8 @@
         }
 
         @Override
-        public NewTabPageDelegate getNewTabPageDelegate() {
-            return NewTabPageDelegate.EMPTY;
+        public NewTabPage getNewTabPageForCurrentTab() {
+            return null;
         }
 
         @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java
index ae3ea94..4595b54d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java
@@ -118,7 +118,7 @@
         private String mUrl;
 
         public TestLocationBarModel() {
-            super(ContextUtils.getApplicationContext(), NewTabPageDelegate.EMPTY);
+            super(ContextUtils.getApplicationContext());
             initializeWithNative();
 
             Tab tab = new MockTab(0, false) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarSecurityIconTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarSecurityIconTest.java
index 341d3702..6582cf5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarSecurityIconTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarSecurityIconTest.java
@@ -63,8 +63,7 @@
         NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
 
         mocker.mock(SecurityStateModelJni.TEST_HOOKS, mSecurityStateMocks);
-        mLocationBarModel = spy(new LocationBarModel(
-                ContextUtils.getApplicationContext(), NewTabPageDelegate.EMPTY));
+        mLocationBarModel = spy(new LocationBarModel(ContextUtils.getApplicationContext()));
         mLocationBarModel.initializeWithNative();
     }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java
index 3c2af79..74cc462 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java
@@ -13,9 +13,9 @@
 import org.robolectric.annotation.Config;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.native_page.NativePageFactory.NativePageType;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.ui.native_page.NativePage;
-import org.chromium.chrome.browser.ui.native_page.NativePage.NativePageType;
 import org.chromium.components.embedder_support.util.UrlConstants;
 
 /**
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandlerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandlerTest.java
index 88a6bb1..99a8db8 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandlerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/LocationBarFocusScrimHandlerTest.java
@@ -23,6 +23,7 @@
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.night_mode.NightModeStateProvider;
+import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.ui.TabObscuringHandler;
 import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
 
@@ -47,7 +48,7 @@
     @Mock
     private ScrimCoordinator mScrimCoordinator;
     @Mock
-    private NewTabPageDelegate mNewTabPageDelegate;
+    private NewTabPage mNewTabPage;
 
     LocationBarFocusScrimHandler mScrimHandler;
 
@@ -62,8 +63,6 @@
 
     @Test
     public void testScrimShown_thenHidden() {
-        doReturn(mNewTabPageDelegate).when(mToolbarDataProvider).getNewTabPageDelegate();
-        doReturn(false).when(mNewTabPageDelegate).isLocationBarShown();
         mScrimHandler.onUrlFocusChange(true);
 
         verify(mScrimCoordinator).showScrim(any());
@@ -78,8 +77,8 @@
 
     @Test
     public void testScrimShown_afterAnimation() {
-        doReturn(mNewTabPageDelegate).when(mToolbarDataProvider).getNewTabPageDelegate();
-        doReturn(true).when(mNewTabPageDelegate).isLocationBarShown();
+        doReturn(mNewTabPage).when(mToolbarDataProvider).getNewTabPageForCurrentTab();
+        doReturn(true).when(mNewTabPage).isLocationBarShownInNTP();
         mScrimHandler.onUrlFocusChange(true);
 
         verify(mScrimCoordinator, never()).showScrim(any());
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java
index 942a28c..277cbe16 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java
@@ -71,14 +71,14 @@
 
     private static class TestIncognitoLocationBarModel extends LocationBarModel {
         public TestIncognitoLocationBarModel(Tab tab) {
-            super(ContextUtils.getApplicationContext(), NewTabPageDelegate.EMPTY);
+            super(ContextUtils.getApplicationContext());
             setTab(tab, /*incognito=*/true);
         }
     }
 
     private static class TestRegularLocationBarModel extends LocationBarModel {
         public TestRegularLocationBarModel(Tab tab) {
-            super(ContextUtils.getApplicationContext(), NewTabPageDelegate.EMPTY);
+            super(ContextUtils.getApplicationContext());
             setTab(tab, /*incognito=*/false);
         }
     }
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 006e1c4..876bd3a1 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-88.0.4300.0_rc-r1-merged.afdo.bz2
+chromeos-chrome-amd64-88.0.4303.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/browser/apps/app_service/borealis_apps.cc b/chrome/browser/apps/app_service/borealis_apps.cc
index 945a117..251028f 100644
--- a/chrome/browser/apps/app_service/borealis_apps.cc
+++ b/chrome/browser/apps/app_service/borealis_apps.cc
@@ -5,8 +5,11 @@
 #include "chrome/browser/apps/app_service/borealis_apps.h"
 
 #include "ash/public/cpp/app_menu_constants.h"
+#include "base/bind.h"
 #include "chrome/browser/apps/app_service/app_icon_factory.h"
 #include "chrome/browser/apps/app_service/menu_util.h"
+#include "chrome/browser/chromeos/borealis/borealis_app_launcher.h"
+#include "chrome/browser/chromeos/borealis/borealis_context_manager.h"
 #include "chrome/browser/chromeos/borealis/borealis_context_manager_factory.h"
 #include "chrome/browser/chromeos/borealis/borealis_context_manager_impl.h"
 #include "chrome/browser/chromeos/borealis/borealis_features.h"
@@ -172,7 +175,18 @@
           ->Features()
           .IsEnabled()) {
     borealis::BorealisContextManagerFactory::GetForProfile(profile_)
-        ->StartBorealis(base::DoNothing());
+        ->StartBorealis(base::BindOnce(
+            [](const std::string& app_id,
+               borealis::BorealisContextManager::Result result) {
+              if (!result.Ok()) {
+                LOG(ERROR) << "Failed to launch " << app_id << ": "
+                           << result.FailureReason();
+                return;
+              }
+              borealis::BorealisAppLauncher::Launch(result.Success(), app_id,
+                                                    base::DoNothing());
+            },
+            app_id));
     return;
   }
   borealis::ShowBorealisInstallerView(profile_);
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 70c05bf..751ee5fd 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -838,6 +838,8 @@
     "bluetooth/debug_logs_manager_factory.h",
     "boot_times_recorder.cc",
     "boot_times_recorder.h",
+    "borealis/borealis_app_launcher.cc",
+    "borealis/borealis_app_launcher.h",
     "borealis/borealis_context.cc",
     "borealis/borealis_context.h",
     "borealis/borealis_context_manager.cc",
@@ -3276,6 +3278,7 @@
     "authpolicy/authpolicy_helper.unittest.cc",
     "base/file_flusher_unittest.cc",
     "bluetooth/debug_logs_manager_unittest.cc",
+    "borealis/borealis_app_launcher_unittest.cc",
     "borealis/borealis_context_manager_unittest.cc",
     "borealis/borealis_features_unittest.cc",
     "borealis/borealis_installer_unittest.cc",
diff --git a/chrome/browser/chromeos/apps/intent_helper/common_apps_navigation_throttle.cc b/chrome/browser/chromeos/apps/intent_helper/common_apps_navigation_throttle.cc
index 3c97a43e..0be75c14 100644
--- a/chrome/browser/chromeos/apps/intent_helper/common_apps_navigation_throttle.cc
+++ b/chrome/browser/chromeos/apps/intent_helper/common_apps_navigation_throttle.cc
@@ -45,7 +45,7 @@
     case apps::mojom::AppType::kWeb:
       picker_entry_type = apps::PickerEntryType::kWeb;
       break;
-    case apps::mojom::AppType::kMacNative:
+    case apps::mojom::AppType::kMacOs:
       picker_entry_type = apps::PickerEntryType::kMacOs;
       break;
   }
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.cc b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.cc
index 6769451..e741186 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.cc
@@ -400,9 +400,7 @@
       type,
       /*title=*/base::string16(), default_path, file_types,
       /*file_type_index=*/0,
-      /*params=*/nullptr, owner,
-      /*search_query=*/"",  // TODO(niwa): Pass request->search_query.
-      show_android_picker_apps);
+      /*params=*/nullptr, owner, search_query, show_android_picker_apps);
   return true;
 }
 
diff --git a/chrome/browser/chromeos/borealis/borealis_app_launcher.cc b/chrome/browser/chromeos/borealis/borealis_app_launcher.cc
new file mode 100644
index 0000000..2c78f07d
--- /dev/null
+++ b/chrome/browser/chromeos/borealis/borealis_app_launcher.cc
@@ -0,0 +1,71 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/borealis/borealis_app_launcher.h"
+
+#include "chrome/browser/chromeos/borealis/borealis_context.h"
+#include "chrome/browser/chromeos/borealis/borealis_util.h"
+#include "chrome/browser/chromeos/guest_os/guest_os_registry_service.h"
+#include "chrome/browser/chromeos/guest_os/guest_os_registry_service_factory.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chromeos/dbus/cicerone/cicerone_service.pb.h"
+#include "chromeos/dbus/cicerone_client.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+
+namespace borealis {
+
+void BorealisAppLauncher::Launch(const BorealisContext& ctx,
+                                 const std::string& app_id,
+                                 OnLaunchedCallback callback) {
+  // Do not launch anything when using the installer app.
+  //
+  // TODO(b/170677773): Launch a _certain_ application...
+  if (app_id == kBorealisAppId) {
+    std::move(callback).Run(kSuccess);
+    return;
+  }
+
+  base::Optional<guest_os::GuestOsRegistryService::Registration> reg =
+      guest_os::GuestOsRegistryServiceFactory::GetForProfile(ctx.profile())
+          ->GetRegistration(app_id);
+
+  if (!reg) {
+    std::move(callback).Run(kUnknownApp);
+    return;
+  }
+
+  vm_tools::cicerone::LaunchContainerApplicationRequest request;
+  request.set_owner_id(
+      chromeos::ProfileHelper::GetUserIdHashFromProfile(ctx.profile()));
+  request.set_vm_name(ctx.vm_name());
+  request.set_container_name(ctx.container_name());
+  request.set_desktop_file_id(reg->DesktopFileId());
+
+  chromeos::DBusThreadManager::Get()
+      ->GetCiceroneClient()
+      ->LaunchContainerApplication(
+          std::move(request),
+          base::BindOnce(
+              [](OnLaunchedCallback callback,
+                 base::Optional<
+                     vm_tools::cicerone::LaunchContainerApplicationResponse>
+                     response) {
+                if (!response) {
+                  LOG(ERROR)
+                      << "Failed to launch app: No response from cicerone";
+                  std::move(callback).Run(kNoResponse);
+                  return;
+                }
+                if (!response->success()) {
+                  LOG(ERROR)
+                      << "Failed to launch app: " << response->failure_reason();
+                  std::move(callback).Run(kError);
+                  return;
+                }
+                std::move(callback).Run(kSuccess);
+              },
+              std::move(callback)));
+}
+
+}  // namespace borealis
diff --git a/chrome/browser/chromeos/borealis/borealis_app_launcher.h b/chrome/browser/chromeos/borealis/borealis_app_launcher.h
new file mode 100644
index 0000000..08b07f97
--- /dev/null
+++ b/chrome/browser/chromeos/borealis/borealis_app_launcher.h
@@ -0,0 +1,35 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_APP_LAUNCHER_H_
+#define CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_APP_LAUNCHER_H_
+
+#include <string>
+
+#include "base/bind_helpers.h"
+
+namespace borealis {
+
+class BorealisContext;
+
+// Helper class responsible for launching borealis' apps.
+class BorealisAppLauncher {
+ public:
+  enum LaunchResult {
+    kSuccess,
+    kUnknownApp,
+    kNoResponse,
+    kError,
+  };
+  using OnLaunchedCallback = base::OnceCallback<void(LaunchResult)>;
+  // Launch the app with the given |app_id| in the borealis instance referred to
+  // by |ctx|.
+  static void Launch(const BorealisContext& ctx,
+                     const std::string& app_id,
+                     OnLaunchedCallback callback);
+};
+
+}  // namespace borealis
+
+#endif  // CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_APP_LAUNCHER_H_
diff --git a/chrome/browser/chromeos/borealis/borealis_app_launcher_unittest.cc b/chrome/browser/chromeos/borealis/borealis_app_launcher_unittest.cc
new file mode 100644
index 0000000..becc56ec
--- /dev/null
+++ b/chrome/browser/chromeos/borealis/borealis_app_launcher_unittest.cc
@@ -0,0 +1,155 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/borealis/borealis_app_launcher.h"
+#include <memory>
+
+#include "base/bind.h"
+#include "base/callback_forward.h"
+#include "base/test/bind_test_util.h"
+#include "chrome/browser/chromeos/borealis/borealis_context.h"
+#include "chrome/browser/chromeos/borealis/borealis_util.h"
+#include "chrome/browser/chromeos/guest_os/guest_os_registry_service.h"
+#include "chrome/browser/chromeos/guest_os/guest_os_registry_service_factory.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_cicerone_client.h"
+#include "chromeos/dbus/vm_applications/apps.pb.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace borealis {
+namespace {
+
+class CallbackFactory
+    : public testing::StrictMock<
+          testing::MockFunction<void(BorealisAppLauncher::LaunchResult)>> {
+ public:
+  base::OnceCallback<void(BorealisAppLauncher::LaunchResult)> BindOnce() {
+    return base::BindOnce(&CallbackFactory::Call, base::Unretained(this));
+  }
+};
+
+class ScopedCiceroneFake {
+ public:
+  ScopedCiceroneFake() { chromeos::DBusThreadManager::Initialize(); }
+
+  ~ScopedCiceroneFake() { chromeos::DBusThreadManager::Shutdown(); }
+
+  chromeos::FakeCiceroneClient* Get() {
+    return reinterpret_cast<chromeos::FakeCiceroneClient*>(
+        chromeos::DBusThreadManager::Get()->GetCiceroneClient());
+  }
+};
+
+class BorealisAppLauncherTest : public testing::Test {
+ public:
+  BorealisAppLauncherTest()
+      : ctx_(BorealisContext::CreateBorealisContextForTesting(&profile_)) {
+    ctx_->set_vm_name("test_vm_name");
+    ctx_->set_container_name("test_container_name");
+  }
+
+ protected:
+  const BorealisContext& Context() { return *ctx_; }
+
+  chromeos::FakeCiceroneClient* Cicerone() { return cicerone_.Get(); }
+
+  // Sets up the registry with a single app. Returns its app id.
+  std::string SetDummyApp(const std::string& desktop_file_id) {
+    vm_tools::apps::ApplicationList list;
+    list.set_vm_name(Context().vm_name());
+    list.set_container_name(Context().container_name());
+    vm_tools::apps::App* app = list.add_apps();
+    app->set_desktop_file_id(desktop_file_id);
+    vm_tools::apps::App::LocaleString::Entry* entry =
+        app->mutable_name()->add_values();
+    entry->set_locale(std::string());
+    entry->set_value(desktop_file_id);
+    app->set_no_display(false);
+    guest_os::GuestOsRegistryServiceFactory::GetForProfile(&profile_)
+        ->UpdateApplicationList(list);
+    return guest_os::GuestOsRegistryService::GenerateAppId(
+        desktop_file_id, list.vm_name(), list.container_name());
+  }
+
+ private:
+  content::BrowserTaskEnvironment task_environment_;
+  ScopedCiceroneFake cicerone_;
+  TestingProfile profile_;
+  std::unique_ptr<BorealisContext> ctx_;
+};
+
+TEST_F(BorealisAppLauncherTest, LauncherAppAlwaysWorks) {
+  CallbackFactory callback_check;
+  EXPECT_CALL(callback_check, Call(BorealisAppLauncher::kSuccess));
+  BorealisAppLauncher::Launch(Context(), kBorealisAppId,
+                              callback_check.BindOnce());
+}
+
+TEST_F(BorealisAppLauncherTest, UnknownAppCausesError) {
+  CallbackFactory callback_check;
+  EXPECT_CALL(callback_check, Call(BorealisAppLauncher::kUnknownApp));
+  BorealisAppLauncher::Launch(Context(), "non_existent_app",
+                              callback_check.BindOnce());
+}
+
+TEST_F(BorealisAppLauncherTest, NoResponseCausesError) {
+  CallbackFactory callback_check;
+  EXPECT_CALL(callback_check, Call(BorealisAppLauncher::kNoResponse));
+  std::string baz_id = SetDummyApp("foo.desktop");
+  Cicerone()->SetOnLaunchContainerApplicationCallback(
+      base::BindLambdaForTesting(
+          [&](const vm_tools::cicerone::LaunchContainerApplicationRequest&
+                  request,
+              chromeos::DBusMethodCallback<
+                  vm_tools::cicerone::LaunchContainerApplicationResponse>
+                  callback) {
+            EXPECT_EQ(request.desktop_file_id(), "foo.desktop");
+            std::move(callback).Run({});
+          }));
+  BorealisAppLauncher::Launch(Context(), baz_id, callback_check.BindOnce());
+}
+
+TEST_F(BorealisAppLauncherTest, ErrorResponseIsPropagated) {
+  CallbackFactory callback_check;
+  EXPECT_CALL(callback_check, Call(BorealisAppLauncher::kError));
+  std::string baz_id = SetDummyApp("bar.desktop");
+  Cicerone()->SetOnLaunchContainerApplicationCallback(
+      base::BindLambdaForTesting(
+          [&](const vm_tools::cicerone::LaunchContainerApplicationRequest&
+                  request,
+              chromeos::DBusMethodCallback<
+                  vm_tools::cicerone::LaunchContainerApplicationResponse>
+                  callback) {
+            EXPECT_EQ(request.desktop_file_id(), "bar.desktop");
+            vm_tools::cicerone::LaunchContainerApplicationResponse response;
+            response.set_success(false);
+            std::move(callback).Run(response);
+          }));
+  BorealisAppLauncher::Launch(Context(), baz_id, callback_check.BindOnce());
+}
+
+TEST_F(BorealisAppLauncherTest, SuccessfulLaunchHasSuccessResponse) {
+  CallbackFactory callback_check;
+  EXPECT_CALL(callback_check, Call(BorealisAppLauncher::kSuccess));
+  std::string baz_id = SetDummyApp("baz.desktop");
+  Cicerone()->SetOnLaunchContainerApplicationCallback(
+      base::BindLambdaForTesting(
+          [&](const vm_tools::cicerone::LaunchContainerApplicationRequest&
+                  request,
+              chromeos::DBusMethodCallback<
+                  vm_tools::cicerone::LaunchContainerApplicationResponse>
+                  callback) {
+            EXPECT_EQ(request.desktop_file_id(), "baz.desktop");
+            vm_tools::cicerone::LaunchContainerApplicationResponse response;
+            response.set_success(true);
+            std::move(callback).Run(response);
+          }));
+  BorealisAppLauncher::Launch(Context(), baz_id, callback_check.BindOnce());
+}
+
+}  // namespace
+}  // namespace borealis
diff --git a/chrome/browser/chromeos/borealis/borealis_context.cc b/chrome/browser/chromeos/borealis/borealis_context.cc
index b3c5397..8afcd3dd 100644
--- a/chrome/browser/chromeos/borealis/borealis_context.cc
+++ b/chrome/browser/chromeos/borealis/borealis_context.cc
@@ -3,11 +3,19 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/borealis/borealis_context.h"
+#include "base/memory/ptr_util.h"
 
 namespace borealis {
 
 BorealisContext::~BorealisContext() = default;
-BorealisContext::BorealisContext() = default;
+
 BorealisContext::BorealisContext(Profile* profile) : profile_(profile) {}
 
+std::unique_ptr<BorealisContext>
+BorealisContext::CreateBorealisContextForTesting(Profile* profile) {
+  // Construct out-of-place because the constructor is private.
+  BorealisContext* ptr = new BorealisContext(profile);
+  return base::WrapUnique(ptr);
+}
+
 }  // namespace borealis
diff --git a/chrome/browser/chromeos/borealis/borealis_context.h b/chrome/browser/chromeos/borealis/borealis_context.h
index 51ee38b1..0a1bd3d 100644
--- a/chrome/browser/chromeos/borealis/borealis_context.h
+++ b/chrome/browser/chromeos/borealis/borealis_context.h
@@ -5,10 +5,12 @@
 #ifndef CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_CONTEXT_H_
 #define CHROME_BROWSER_CHROMEOS_BOREALIS_BOREALIS_CONTEXT_H_
 
+#include <memory>
 #include <string>
 
 #include "base/files/file_path.h"
-#include "chrome/browser/profiles/profile.h"
+
+class Profile;
 
 namespace borealis {
 
@@ -21,12 +23,10 @@
   BorealisContext& operator=(const BorealisContext&) = delete;
   ~BorealisContext();
 
-  static BorealisContext* CreateBorealisContextForTesting() {
-    return new BorealisContext();
-  }
+  static std::unique_ptr<BorealisContext> CreateBorealisContextForTesting(
+      Profile* profile);
 
-  Profile* profile() { return profile_; }
-  void set_profile(Profile* profile) { profile_ = profile; }
+  Profile* profile() const { return profile_; }
 
   bool borealis_running() const { return borealis_running_; }
   void set_borealis_running(bool success) { borealis_running_ = success; }
@@ -48,10 +48,9 @@
  private:
   friend class BorealisContextManagerImpl;
 
-  BorealisContext();
   explicit BorealisContext(Profile* profile);
 
-  Profile* profile_ = nullptr;
+  Profile* const profile_;
   bool borealis_running_ = false;
   std::string vm_name_;
   std::string container_name_;
diff --git a/chrome/browser/chromeos/borealis/borealis_context_manager.h b/chrome/browser/chromeos/borealis/borealis_context_manager.h
index 78313ded..8c588da 100644
--- a/chrome/browser/chromeos/borealis/borealis_context_manager.h
+++ b/chrome/browser/chromeos/borealis/borealis_context_manager.h
@@ -22,6 +22,7 @@
     kMountFailed = 1,
     kDiskImageFailed = 2,
     kStartVmFailed = 3,
+    kAwaitBorealisStartupFailed = 4,
   };
 
   // An attempt to launch borealis. If the launch succeeds, holds a reference to
diff --git a/chrome/browser/chromeos/borealis/borealis_context_manager_impl.cc b/chrome/browser/chromeos/borealis/borealis_context_manager_impl.cc
index f555519e..32cece4 100644
--- a/chrome/browser/chromeos/borealis/borealis_context_manager_impl.cc
+++ b/chrome/browser/chromeos/borealis/borealis_context_manager_impl.cc
@@ -23,6 +23,8 @@
       return stream << "Disk Image Failed";
     case borealis::BorealisContextManager::kStartVmFailed:
       return stream << "Start VM Failed";
+    case borealis::BorealisContextManager::kAwaitBorealisStartupFailed:
+      return stream << "Await Borealis Startup Failed";
   }
 }
 
@@ -50,11 +52,15 @@
 
 base::queue<std::unique_ptr<BorealisTask>>
 BorealisContextManagerImpl::GetTasks() {
+  // We use a hard-coded name. When multi-instance becomes a feature we'll
+  // need to determine the name instead.
+  context_.set_vm_name("borealis");
   base::queue<std::unique_ptr<BorealisTask>> task_queue;
   task_queue.push(std::make_unique<MountDlc>());
   task_queue.push(std::make_unique<CreateDiskImage>());
   task_queue.push(std::make_unique<StartBorealisVm>());
-  task_queue.push(std::make_unique<AwaitBorealisStartup>());
+  task_queue.push(std::make_unique<AwaitBorealisStartup>(context_.profile(),
+                                                         context_.vm_name()));
   return task_queue;
 }
 
diff --git a/chrome/browser/chromeos/borealis/borealis_installer_impl.cc b/chrome/browser/chromeos/borealis/borealis_installer_impl.cc
index 5594e3f..a7f5b05 100644
--- a/chrome/browser/chromeos/borealis/borealis_installer_impl.cc
+++ b/chrome/browser/chromeos/borealis/borealis_installer_impl.cc
@@ -46,7 +46,9 @@
 }
 
 void BorealisInstallerImpl::Cancel() {
-  state_ = State::kCancelling;
+  if (state_ != State::kIdle) {
+    state_ = State::kCancelling;
+  }
   for (auto& observer : observers_) {
     observer.OnCancelInitiated();
   }
diff --git a/chrome/browser/chromeos/borealis/borealis_installer_unittest.cc b/chrome/browser/chromeos/borealis/borealis_installer_unittest.cc
index 0d42470..ba6fa4a0 100644
--- a/chrome/browser/chromeos/borealis/borealis_installer_unittest.cc
+++ b/chrome/browser/chromeos/borealis/borealis_installer_unittest.cc
@@ -196,6 +196,33 @@
       BorealisService::GetForProfile(profile_.get())->Features().IsEnabled());
 }
 
+TEST_F(BorealisInstallerTest, CancelledThenSuccessfulInstallation) {
+  feature_list_.InitAndEnableFeature(features::kBorealis);
+  fake_dlcservice_client_->set_install_error(dlcservice::kErrorNone);
+
+  EXPECT_CALL(*observer_, OnCancelInitiated());
+
+  installer_->Cancel();
+  task_environment_.RunUntilIdle();
+
+  UpdateCurrentDlcs();
+  ASSERT_EQ(current_dlcs_.dlc_infos_size(), 0);
+  EXPECT_FALSE(
+      BorealisService::GetForProfile(profile_.get())->Features().IsEnabled());
+
+  ExpectObserverEventsUntil(InstallingState::kInstallingDlc);
+  EXPECT_CALL(*observer_, OnInstallationEnded(InstallationResult::kCompleted));
+
+  installer_->Start();
+  task_environment_.RunUntilIdle();
+
+  UpdateCurrentDlcs();
+  ASSERT_EQ(current_dlcs_.dlc_infos_size(), 1);
+  EXPECT_EQ(current_dlcs_.dlc_infos(0).id(), borealis::kBorealisDlcName);
+  EXPECT_TRUE(
+      BorealisService::GetForProfile(profile_.get())->Features().IsEnabled());
+}
+
 // Note that we don't check if the DLC has/hasn't been installed, since the
 // mocked DLC service will always suceeed, so we only care about how the error
 // code returned by the service is handled by the installer.
diff --git a/chrome/browser/chromeos/borealis/borealis_launch_watcher.h b/chrome/browser/chromeos/borealis/borealis_launch_watcher.h
index ba19e75..a7e52f8 100644
--- a/chrome/browser/chromeos/borealis/borealis_launch_watcher.h
+++ b/chrome/browser/chromeos/borealis/borealis_launch_watcher.h
@@ -45,7 +45,7 @@
 
   std::string owner_id_;
   std::string vm_name_;
-  base::TimeDelta timeout_ = base::TimeDelta::FromMilliseconds(5000);
+  base::TimeDelta timeout_ = base::TimeDelta::FromMilliseconds(30000);
   base::Optional<vm_tools::cicerone::ContainerStartedSignal>
       container_started_signal_;
   base::queue<OnLaunchCallback> callback_queue_;
diff --git a/chrome/browser/chromeos/borealis/borealis_task.cc b/chrome/browser/chromeos/borealis/borealis_task.cc
index 14f5333..e631db1 100644
--- a/chrome/browser/chromeos/borealis/borealis_task.cc
+++ b/chrome/browser/chromeos/borealis/borealis_task.cc
@@ -48,9 +48,6 @@
 
 void CreateDiskImage::Run(BorealisContext* context,
                           CompletionStatusCallback callback) {
-  // We use a hard-coded name. When multi-instance becomes a feature we'll
-  // need to determine the name instead.
-  context->set_vm_name("borealis");
   vm_tools::concierge::CreateDiskImageRequest request;
   request.set_disk_path(context->vm_name());
   request.set_cryptohome_id(
@@ -147,12 +144,32 @@
           base::NumberToString(response->status()) + ")");
 }
 
+AwaitBorealisStartup::AwaitBorealisStartup(Profile* profile,
+                                           std::string vm_name)
+    : watcher_(profile, vm_name) {}
+AwaitBorealisStartup::~AwaitBorealisStartup() = default;
+
 void AwaitBorealisStartup::Run(BorealisContext* context,
                                CompletionStatusCallback callback) {
-  // TODO(b/170696557): Refactor to use the LaunchWatcher which is not finished
-  // yet. In our case the name is hard-coded, so we can use that.
-  context->set_container_name("penguin");
-  std::move(callback).Run(BorealisContextManager::kSuccess, "");
+  watcher_.AwaitLaunch(
+      base::BindOnce(&AwaitBorealisStartup::OnAwaitBorealisStartup,
+                     weak_factory_.GetWeakPtr(), context, std::move(callback)));
 }
 
+BorealisLaunchWatcher& AwaitBorealisStartup::GetWatcherForTesting() {
+  return watcher_;
+}
+
+void AwaitBorealisStartup::OnAwaitBorealisStartup(
+    BorealisContext* context,
+    CompletionStatusCallback callback,
+    base::Optional<std::string> container) {
+  if (!container) {
+    std::move(callback).Run(BorealisContextManager::kAwaitBorealisStartupFailed,
+                            "Awaiting for Borealis launch failed: timed out");
+    return;
+  }
+  context->set_container_name(container.value());
+  std::move(callback).Run(BorealisContextManager::kSuccess, "");
+}
 }  // namespace borealis
diff --git a/chrome/browser/chromeos/borealis/borealis_task.h b/chrome/browser/chromeos/borealis/borealis_task.h
index 0287cd5..d301ee7 100644
--- a/chrome/browser/chromeos/borealis/borealis_task.h
+++ b/chrome/browser/chromeos/borealis/borealis_task.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/borealis/borealis_context_manager.h"
+#include "chrome/browser/chromeos/borealis/borealis_launch_watcher.h"
 #include "chromeos/dbus/concierge_client.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
 
@@ -82,8 +83,18 @@
 // Waits for the startup daemon to signal completion.
 class AwaitBorealisStartup : public BorealisTask {
  public:
+  AwaitBorealisStartup(Profile* profile, std::string vm_name);
+  ~AwaitBorealisStartup() override;
   void Run(BorealisContext* context,
            CompletionStatusCallback callback) override;
+  BorealisLaunchWatcher& GetWatcherForTesting();
+
+ private:
+  void OnAwaitBorealisStartup(BorealisContext* context,
+                              CompletionStatusCallback callback,
+                              base::Optional<std::string> container);
+  BorealisLaunchWatcher watcher_;
+  base::WeakPtrFactory<AwaitBorealisStartup> weak_factory_{this};
 };
 
 }  // namespace borealis
diff --git a/chrome/browser/chromeos/borealis/borealis_task_unittest.cc b/chrome/browser/chromeos/borealis/borealis_task_unittest.cc
index ebad5fe8..f6219eb 100644
--- a/chrome/browser/chromeos/borealis/borealis_task_unittest.cc
+++ b/chrome/browser/chromeos/borealis/borealis_task_unittest.cc
@@ -8,9 +8,11 @@
 
 #include "chrome/browser/chromeos/borealis/borealis_context.h"
 #include "chrome/browser/chromeos/borealis/borealis_context_manager.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/dlcservice/fake_dlcservice_client.h"
+#include "chromeos/dbus/fake_cicerone_client.h"
 #include "chromeos/dbus/fake_concierge_client.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -49,9 +51,11 @@
     chromeos::DBusThreadManager::Initialize();
     fake_concierge_client_ = static_cast<chromeos::FakeConciergeClient*>(
         chromeos::DBusThreadManager::Get()->GetConciergeClient());
+    fake_cicerone_client_ = static_cast<chromeos::FakeCiceroneClient*>(
+        chromeos::DBusThreadManager::Get()->GetCiceroneClient());
     CreateProfile();
-    context_ = BorealisContext::CreateBorealisContextForTesting();
-    context_->set_profile(profile_.get());
+    context_ = BorealisContext::CreateBorealisContextForTesting(profile_.get());
+    context_->set_vm_name("borealis");
 
     chromeos::DlcserviceClient::InitializeFake();
     fake_dlcservice_client_ = static_cast<chromeos::FakeDlcserviceClient*>(
@@ -66,10 +70,11 @@
   }
 
   std::unique_ptr<TestingProfile> profile_;
-  BorealisContext* context_;
+  std::unique_ptr<BorealisContext> context_;
   content::BrowserTaskEnvironment task_environment_;
   // Owned by chromeos::DBusThreadManager
   chromeos::FakeConciergeClient* fake_concierge_client_;
+  chromeos::FakeCiceroneClient* fake_cicerone_client_;
   chromeos::FakeDlcserviceClient* fake_dlcservice_client_;
 
  private:
@@ -89,7 +94,7 @@
   EXPECT_CALL(callback, Callback(BorealisContextManager::kSuccess, _));
 
   MountDlc task;
-  task.Run(context_, callback.GetCallback());
+  task.Run(context_.get(), callback.GetCallback());
   task_environment_.RunUntilIdle();
 
   EXPECT_EQ(context_->root_path(), "test/path");
@@ -107,7 +112,7 @@
   EXPECT_CALL(callback, Callback(BorealisContextManager::kSuccess, _));
 
   CreateDiskImage task;
-  task.Run(context_, callback.GetCallback());
+  task.Run(context_.get(), callback.GetCallback());
   task_environment_.RunUntilIdle();
 
   EXPECT_TRUE(fake_concierge_client_->create_disk_image_called());
@@ -127,7 +132,7 @@
   EXPECT_CALL(callback, Callback(BorealisContextManager::kSuccess, _));
 
   CreateDiskImage task;
-  task.Run(context_, callback.GetCallback());
+  task.Run(context_.get(), callback.GetCallback());
   task_environment_.RunUntilIdle();
 
   EXPECT_TRUE(fake_concierge_client_->create_disk_image_called());
@@ -143,7 +148,7 @@
   EXPECT_CALL(callback, Callback(BorealisContextManager::kSuccess, _));
 
   StartBorealisVm task;
-  task.Run(context_, callback.GetCallback());
+  task.Run(context_.get(), callback.GetCallback());
   task_environment_.RunUntilIdle();
 
   EXPECT_TRUE(fake_concierge_client_->start_termina_vm_called());
@@ -159,12 +164,61 @@
   EXPECT_CALL(callback, Callback(BorealisContextManager::kSuccess, _));
 
   StartBorealisVm task;
-  task.Run(context_, callback.GetCallback());
+  task.Run(context_.get(), callback.GetCallback());
   task_environment_.RunUntilIdle();
 
   EXPECT_TRUE(fake_concierge_client_->start_termina_vm_called());
 }
 
+TEST_F(BorealisTasksTest,
+       AwaitBorealisStartupSucceedsAndCallbackRanWithResults) {
+  vm_tools::cicerone::ContainerStartedSignal signal;
+  signal.set_owner_id(
+      chromeos::ProfileHelper::GetUserIdHashFromProfile(context_->profile()));
+  signal.set_vm_name(context_->vm_name());
+  signal.set_container_name("penguin");
+
+  testing::StrictMock<CallbackForTesting> callback;
+  EXPECT_CALL(callback, Callback(BorealisContextManager::kSuccess, _));
+
+  AwaitBorealisStartup task(context_->profile(), context_->vm_name());
+  task.Run(context_.get(), callback.GetCallback());
+  fake_cicerone_client_->NotifyContainerStarted(std::move(signal));
+
+  task_environment_.RunUntilIdle();
+}
+
+TEST_F(BorealisTasksTest,
+       AwaitBorealisStartupContainerAlreadyStartedAndCallbackRanWithResults) {
+  vm_tools::cicerone::ContainerStartedSignal signal;
+  signal.set_owner_id(
+      chromeos::ProfileHelper::GetUserIdHashFromProfile(context_->profile()));
+  signal.set_vm_name(context_->vm_name());
+  signal.set_container_name("penguin");
+
+  testing::StrictMock<CallbackForTesting> callback;
+  EXPECT_CALL(callback, Callback(BorealisContextManager::kSuccess, _));
+
+  AwaitBorealisStartup task(context_->profile(), context_->vm_name());
+  fake_cicerone_client_->NotifyContainerStarted(std::move(signal));
+  task.Run(context_.get(), callback.GetCallback());
+  task_environment_.RunUntilIdle();
+}
+
+TEST_F(BorealisTasksTest,
+       AwaitBorealisStartupTimesOutAndCallbackRanWithResults) {
+  testing::StrictMock<CallbackForTesting> callback;
+  EXPECT_CALL(
+      callback,
+      Callback(BorealisContextManager::kAwaitBorealisStartupFailed, StrNe("")));
+
+  AwaitBorealisStartup task(context_->profile(), context_->vm_name());
+  task.GetWatcherForTesting().SetTimeoutForTesting(
+      base::TimeDelta::FromMilliseconds(0));
+  task.Run(context_.get(), callback.GetCallback());
+  task_environment_.RunUntilIdle();
+}
+
 class BorealisTasksTestDlc : public BorealisTasksTest,
                              public testing::WithParamInterface<std::string> {};
 
@@ -175,7 +229,7 @@
               Callback(BorealisContextManager::kMountFailed, StrNe("")));
 
   MountDlc task;
-  task.Run(context_, callback.GetCallback());
+  task.Run(context_.get(), callback.GetCallback());
   task_environment_.RunUntilIdle();
 }
 
@@ -204,7 +258,7 @@
               Callback(BorealisContextManager::kDiskImageFailed, StrNe("")));
 
   CreateDiskImage task;
-  task.Run(context_, callback.GetCallback());
+  task.Run(context_.get(), callback.GetCallback());
   task_environment_.RunUntilIdle();
 
   EXPECT_TRUE(fake_concierge_client_->create_disk_image_called());
@@ -236,7 +290,7 @@
               Callback(BorealisContextManager::kStartVmFailed, StrNe("")));
 
   StartBorealisVm task;
-  task.Run(context_, callback.GetCallback());
+  task.Run(context_.get(), callback.GetCallback());
   task_environment_.RunUntilIdle();
 
   EXPECT_TRUE(fake_concierge_client_->start_termina_vm_called());
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_types.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_types.cc
index 2df8a10..68b7a7be 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_types.cc
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_types.cc
@@ -29,8 +29,8 @@
       return "Built in";
     case apps::mojom::AppType::kCrostini:
       return "Crostini";
-    case apps::mojom::AppType::kMacNative:
-      return "Mac native";
+    case apps::mojom::AppType::kMacOs:
+      return "Mac OS";
     case apps::mojom::AppType::kPluginVm:
       return "Plugin VM";
     case apps::mojom::AppType::kLacros:
diff --git a/chrome/browser/chromeos/crostini/crostini_test_helper.cc b/chrome/browser/chromeos/crostini/crostini_test_helper.cc
index fcb862a..d7965350 100644
--- a/chrome/browser/chromeos/crostini/crostini_test_helper.cc
+++ b/chrome/browser/chromeos/crostini/crostini_test_helper.cc
@@ -150,8 +150,8 @@
     const std::string& desktop_file_id,
     const std::string& vm_name,
     const std::string& container_name) {
-  return crx_file::id_util::GenerateId("crostini:" + vm_name + "/" +
-                                       container_name + "/" + desktop_file_id);
+  return guest_os::GuestOsRegistryService::GenerateAppId(
+      desktop_file_id, vm_name, container_name);
 }
 
 // static
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
index eedc38b1..d9390ef 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -318,8 +318,8 @@
       return api::autotest_private::AppType::APP_TYPE_WEB;
     case apps::mojom::AppType::kUnknown:
       return api::autotest_private::AppType::APP_TYPE_NONE;
-    case apps::mojom::AppType::kMacNative:
-      return api::autotest_private::AppType::APP_TYPE_MACNATIVE;
+    case apps::mojom::AppType::kMacOs:
+      return api::autotest_private::AppType::APP_TYPE_MACOS;
     case apps::mojom::AppType::kLacros:
       return api::autotest_private::AppType::APP_TYPE_LACROS;
     case apps::mojom::AppType::kRemote:
diff --git a/chrome/browser/chromeos/file_manager/app_service_file_tasks.cc b/chrome/browser/chromeos/file_manager/app_service_file_tasks.cc
index 0c08370e..2818953 100644
--- a/chrome/browser/chromeos/file_manager/app_service_file_tasks.cc
+++ b/chrome/browser/chromeos/file_manager/app_service_file_tasks.cc
@@ -51,7 +51,7 @@
     case apps::mojom::AppType::kCrostini:
     case apps::mojom::AppType::kBuiltIn:
     case apps::mojom::AppType::kExtension:
-    case apps::mojom::AppType::kMacNative:
+    case apps::mojom::AppType::kMacOs:
     case apps::mojom::AppType::kPluginVm:
     case apps::mojom::AppType::kLacros:
     case apps::mojom::AppType::kRemote:
diff --git a/chrome/browser/chromeos/file_manager/file_tasks.cc b/chrome/browser/chromeos/file_manager/file_tasks.cc
index dd7ef65..864e99c 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks.cc
+++ b/chrome/browser/chromeos/file_manager/file_tasks.cc
@@ -47,6 +47,7 @@
 #include "chrome/common/extensions/api/file_manager_private.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "components/drive/drive_api_util.h"
 #include "components/prefs/pref_service.h"
@@ -170,6 +171,20 @@
   tasks->swap(filtered);
 }
 
+// Returns whether |path| is a RAW image file according to its extension. Note
+// that since none of the extensions of interest are "known" mime types (per
+// net/mime_util.cc), it's enough to simply check the extension rather than
+// using MimeTypeCollector. TODO(crbug/1030935): Remove this.
+bool IsRawImage(const base::FilePath& path) {
+  constexpr const char* kRawExtensions[] = {".arw", ".cr2", ".dng", ".nef",
+                                            ".nrw", ".orf", ".raf", ".rw2"};
+  for (const char* extension : kRawExtensions) {
+    if (path.MatchesExtension(extension))
+      return true;
+  }
+  return false;
+}
+
 // Adjusts |tasks| to reflect the product decision that chrome://media-app
 // should behave more like a user-installed app than a fallback handler.
 // Specifically, only apps set as the default in user prefs should be preferred
@@ -192,13 +207,15 @@
   if (media_app_task == tasks->end())
     return;
 
-  // TODO(crbug/1030935): Once Media app supports RAW files, delete the
-  // IsRawImage early exit. This is necessary while Gallery is still the
-  // better option for RAW files. The any_non_image check can be removed once
-  // video player functionality of the Media App is fully polished.
+  // TODO(crbug/1030935): Delete the IsRawImage function and early exit when
+  // kMediaAppHandlesRaw is removed. The any_non_image check can be removed once
+  // video player functionality of the Media App is fully polished
+  // (b/171154148).
   bool any_non_image = false;
   for (const auto& entry : entries) {
-    if (IsRawImage(entry.path)) {
+    if (!base::FeatureList::IsEnabled(
+            chromeos::features::kMediaAppHandlesRaw) &&
+        IsRawImage(entry.path)) {
       tasks->erase(media_app_task);
       return;  // Let Gallery handle it.
     }
@@ -914,16 +931,6 @@
   }
 }
 
-bool IsRawImage(const base::FilePath& path) {
-  constexpr const char* kRawExtensions[] = {".arw", ".cr2", ".dng", ".nef",
-                                            ".nrw", ".orf", ".raf", ".rw2"};
-  for (const char* extension : kRawExtensions) {
-    if (path.MatchesExtension(extension))
-      return true;
-  }
-  return false;
-}
-
 bool IsHtmlFile(const base::FilePath& path) {
   constexpr const char* kHtmlExtensions[] = {".htm", ".html", ".mhtml",
                                              ".xht", ".xhtm", ".xhtml"};
diff --git a/chrome/browser/chromeos/file_manager/file_tasks.h b/chrome/browser/chromeos/file_manager/file_tasks.h
index 50eab36b..aebcf3a1 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks.h
+++ b/chrome/browser/chromeos/file_manager/file_tasks.h
@@ -340,12 +340,6 @@
                              const std::vector<extensions::EntryInfo>& entries,
                              std::vector<FullTaskDescriptor>* tasks);
 
-// Returns whether |path| is a RAW image file according to its extension. Note
-// that since none of the extensions of interest are "known" mime types (per
-// net/mime_util.cc), it's enough to simply check the extension rather than
-// using MimeTypeCollector. TODO(crbug/1030935): Remove this.
-bool IsRawImage(const base::FilePath& path);
-
 // Returns whether |path| is an HTML file according to its extension.
 bool IsHtmlFile(const base::FilePath& path);
 
diff --git a/chrome/browser/chromeos/file_manager/file_tasks_browsertest.cc b/chrome/browser/chromeos/file_manager/file_tasks_browsertest.cc
index c45f3ea..fe218ad 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_tasks_browsertest.cc
@@ -126,13 +126,14 @@
         base::FilePath path = prefix.AddExtension(extension);
         std::string mime_type;
         net::GetMimeTypeFromFile(path, &mime_type);
-        if (test.mime_type) {
+        if (test.mime_type != nullptr) {
           // Sniffing isn't used when GetMimeTypeFromFile() succeeds, so there
           // shouldn't be a hard-coded mime type configured.
           EXPECT_TRUE(mime_type.empty());
           mime_type = test.mime_type;
+        } else {
+          EXPECT_FALSE(mime_type.empty()) << "No mime type for " << path;
         }
-        EXPECT_FALSE(mime_type.empty()) << "No mime type for " << path;
         entries.push_back({path, mime_type, false});
       }
       std::vector<GURL> file_urls{entries.size(), GURL()};
@@ -160,8 +161,24 @@
 class FileTasksBrowserTestWithMediaApp : public FileTasksBrowserTestBase {
  public:
   FileTasksBrowserTestWithMediaApp() {
-    // Enable Media App.
-    scoped_feature_list_.InitWithFeatures({chromeos::features::kMediaApp}, {});
+    // Enable Media App with Raw support.
+    scoped_feature_list_.InitWithFeatures(
+        {chromeos::features::kMediaApp,
+         chromeos::features::kMediaAppHandlesRaw},
+        {});
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+class FileTasksBrowserTestWithMediaAppNoRaw : public FileTasksBrowserTestBase {
+ public:
+  FileTasksBrowserTestWithMediaAppNoRaw() {
+    // Enable Media App. Disable Raw support.
+    scoped_feature_list_.InitWithFeatures(
+        {chromeos::features::kMediaApp},
+        {chromeos::features::kMediaAppHandlesRaw});
   }
 
  private:
@@ -179,17 +196,6 @@
 // not operate on real files. We hard code MIME types that file sniffing
 // obtained experimentally from sample files.
 constexpr Expectation kUnchangedExpectations[] = {
-    // Raw.
-    {"arw", kGalleryAppId, "image/tiff"},
-    {"cr2", kGalleryAppId, "image/tiff"},
-    {"dng", kGalleryAppId, "image/tiff"},
-    {"nef", kGalleryAppId, "image/tiff"},
-    {"nrw", kGalleryAppId, "image/tiff"},
-    {"orf", kGalleryAppId, "image/tiff"},
-    {"raf", kGalleryAppId, "image/tiff"},
-    {"rw2", kGalleryAppId, "image/tiff"},
-    {"NRW", kGalleryAppId, "image/tiff"},  // Uppercase extension.
-
     // Video.
     {"3gp", kVideoPlayerAppId, "application/octet-stream"},
     {"avi", kVideoPlayerAppId, "application/octet-stream"},
@@ -293,9 +299,24 @@
   //  With the Media App disabled, all images should be handled by Gallery.
   std::vector<Expectation> expectations = {
       // Images.
-      {"bmp", kGalleryAppId},  {"gif", kGalleryAppId},  {"ico", kGalleryAppId},
-      {"jpg", kGalleryAppId},  {"jpeg", kGalleryAppId}, {"png", kGalleryAppId},
+      {"bmp", kGalleryAppId},
+      {"gif", kGalleryAppId},
+      {"ico", kGalleryAppId},
+      {"jpg", kGalleryAppId},
+      {"jpeg", kGalleryAppId},
+      {"png", kGalleryAppId},
       {"webp", kGalleryAppId},
+      // Raw.
+      {"arw", kGalleryAppId, "image/tiff"},
+      {"cr2", kGalleryAppId, "image/tiff"},
+      {"dng", kGalleryAppId, "image/tiff"},
+      {"nef", kGalleryAppId, "image/tiff"},
+      {"nrw", kGalleryAppId, "image/tiff"},
+      {"orf", kGalleryAppId, "image/tiff"},
+      {"raf", kGalleryAppId, "image/tiff"},
+      {"rw2", kGalleryAppId, "image/tiff"},
+      {"NRW", kGalleryAppId, "image/tiff"},  // Uppercase extension.
+      {"arw", kGalleryAppId, ""},  // Missing MIME type (unable to sniff).
   };
   expectations.insert(expectations.end(), std::begin(kUnchangedExpectations),
                       std::end(kUnchangedExpectations));
@@ -321,9 +342,57 @@
   // video, which it also handles should be unchanged).
   std::vector<Expectation> expectations = {
       // Images.
-      {"bmp", kMediaAppId},  {"gif", kMediaAppId},  {"ico", kMediaAppId},
-      {"jpg", kMediaAppId},  {"jpeg", kMediaAppId}, {"png", kMediaAppId},
+      {"bmp", kMediaAppId},
+      {"gif", kMediaAppId},
+      {"ico", kMediaAppId},
+      {"jpg", kMediaAppId},
+      {"jpeg", kMediaAppId},
+      {"png", kMediaAppId},
       {"webp", kMediaAppId},
+      // Raw (handled by MediaApp).
+      {"arw", kMediaAppId, "image/tiff"},
+      {"cr2", kMediaAppId, "image/tiff"},
+      {"dng", kMediaAppId, "image/tiff"},
+      {"nef", kMediaAppId, "image/tiff"},
+      {"nrw", kMediaAppId, "image/tiff"},
+      {"orf", kMediaAppId, "image/tiff"},
+      {"raf", kMediaAppId, "image/tiff"},
+      {"rw2", kMediaAppId, "image/tiff"},
+      {"NRW", kMediaAppId, "image/tiff"},  // Uppercase extension.
+      {"arw", kMediaAppId, ""},  // Missing MIME type (unable to sniff).
+  };
+  expectations.insert(expectations.end(), std::begin(kUnchangedExpectations),
+                      std::end(kUnchangedExpectations));
+
+  TestExpectationsAgainstDefaultTasks(expectations);
+}
+
+// Tests the default handlers with the Media App installed, but RAW support
+// disabled.
+IN_PROC_BROWSER_TEST_P(FileTasksBrowserTestWithMediaAppNoRaw,
+                       DefaultHandlerChangeDetector) {
+  // With the Media App enabled, images should be handled by it by default (but
+  // video, which it also handles should be unchanged).
+  std::vector<Expectation> expectations = {
+      // Images.
+      {"bmp", kMediaAppId},
+      {"gif", kMediaAppId},
+      {"ico", kMediaAppId},
+      {"jpg", kMediaAppId},
+      {"jpeg", kMediaAppId},
+      {"png", kMediaAppId},
+      {"webp", kMediaAppId},
+      // Raw (still handled by gallery).
+      {"arw", kGalleryAppId, "image/tiff"},
+      {"cr2", kGalleryAppId, "image/tiff"},
+      {"dng", kGalleryAppId, "image/tiff"},
+      {"nef", kGalleryAppId, "image/tiff"},
+      {"nrw", kGalleryAppId, "image/tiff"},
+      {"orf", kGalleryAppId, "image/tiff"},
+      {"raf", kGalleryAppId, "image/tiff"},
+      {"rw2", kGalleryAppId, "image/tiff"},
+      {"NRW", kGalleryAppId, "image/tiff"},  // Uppercase extension.
+      {"arw", kGalleryAppId, ""},  // Missing MIME type (unable to sniff).
   };
   expectations.insert(expectations.end(), std::begin(kUnchangedExpectations),
                       std::end(kUnchangedExpectations));
@@ -460,5 +529,12 @@
                                            TestProfileType::kGuest),
                          TestProfileTypeToString);
 
+INSTANTIATE_TEST_SUITE_P(All,
+                         FileTasksBrowserTestWithMediaAppNoRaw,
+                         ::testing::Values(TestProfileType::kRegular,
+                                           TestProfileType::kIncognito,
+                                           TestProfileType::kGuest),
+                         TestProfileTypeToString);
+
 }  // namespace file_tasks
 }  // namespace file_manager
diff --git a/chrome/browser/chromeos/guest_os/guest_os_registry_service.cc b/chrome/browser/chromeos/guest_os/guest_os_registry_service.cc
index f572d7d..694a0434 100644
--- a/chrome/browser/chromeos/guest_os/guest_os_registry_service.cc
+++ b/chrome/browser/chromeos/guest_os/guest_os_registry_service.cc
@@ -57,16 +57,6 @@
 constexpr char kPluginVmAppsInstalledHistogram[] =
     "PluginVm.AppsInstalledAtLogin";
 
-std::string GenerateAppId(const std::string& desktop_file_id,
-                          const std::string& vm_name,
-                          const std::string& container_name) {
-  // These can collide in theory because the user could choose VM and container
-  // names which contain slashes, but this will only result in apps missing from
-  // the launcher.
-  return crx_file::id_util::GenerateId(kCrostiniAppIdPrefix + vm_name + "/" +
-                                       container_name + "/" + desktop_file_id);
-}
-
 base::Value ProtoToDictionary(const App::LocaleString& locale_string) {
   base::Value result(base::Value::Type::DICTIONARY);
   for (const App::LocaleString::Entry& entry : locale_string.values()) {
@@ -1040,6 +1030,18 @@
   app->SetKey(guest_os::prefs::kAppScaledKey, base::Value(scaled));
 }
 
+// static
+std::string GuestOsRegistryService::GenerateAppId(
+    const std::string& desktop_file_id,
+    const std::string& vm_name,
+    const std::string& container_name) {
+  // These can collide in theory because the user could choose VM and container
+  // names which contain slashes, but this will only result in apps missing from
+  // the launcher.
+  return crx_file::id_util::GenerateId(kCrostiniAppIdPrefix + vm_name + "/" +
+                                       container_name + "/" + desktop_file_id);
+}
+
 void GuestOsRegistryService::RequestContainerAppIcon(
     const std::string& app_id,
     ui::ScaleFactor scale_factor) {
diff --git a/chrome/browser/chromeos/guest_os/guest_os_registry_service.h b/chrome/browser/chromeos/guest_os/guest_os_registry_service.h
index 658266f..5b57ba1b 100644
--- a/chrome/browser/chromeos/guest_os/guest_os_registry_service.h
+++ b/chrome/browser/chromeos/guest_os/guest_os_registry_service.h
@@ -218,6 +218,12 @@
 
   void SetClockForTesting(base::Clock* clock) { clock_ = clock; }
 
+  // Returns the AppId that will be used to refer to the given GuestOs
+  // application.
+  static std::string GenerateAppId(const std::string& desktop_file_id,
+                                   const std::string& vm_name,
+                                   const std::string& container_name);
+
  private:
   // Run start up tasks for the registry (e.g. recording metrics).
   void RecordStartupMetrics();
diff --git a/chrome/browser/chromeos/input_method/assistive_window_controller.cc b/chrome/browser/chromeos/input_method/assistive_window_controller.cc
index 859c808..3e99ff08 100644
--- a/chrome/browser/chromeos/input_method/assistive_window_controller.cc
+++ b/chrome/browser/chromeos/input_method/assistive_window_controller.cc
@@ -172,11 +172,6 @@
   suggestion_window_view_->Show(details);
 }
 
-// TODO(crbug/1102219): Method unused. Remove all definitions and references.
-void AssistiveWindowController::ShowMultipleSuggestions(
-    const std::vector<base::string16>& suggestions) {
-}
-
 void AssistiveWindowController::SetButtonHighlighted(
     const ui::ime::AssistiveWindowButton& button,
     bool highlighted) {
diff --git a/chrome/browser/chromeos/input_method/assistive_window_controller.h b/chrome/browser/chromeos/input_method/assistive_window_controller.h
index 9b28ae9..7023452 100644
--- a/chrome/browser/chromeos/input_method/assistive_window_controller.h
+++ b/chrome/browser/chromeos/input_method/assistive_window_controller.h
@@ -73,8 +73,6 @@
   void SetAssistiveWindowProperties(
       const AssistiveWindowProperties& window) override;
   void ShowSuggestion(const ui::ime::SuggestionDetails& details) override;
-  void ShowMultipleSuggestions(
-      const std::vector<base::string16>& suggestions) override;
   void SetButtonHighlighted(const ui::ime::AssistiveWindowButton& button,
                             bool highlighted) override;
   void AcceptSuggestion(const base::string16& suggestion) override;
diff --git a/chrome/browser/chromeos/input_method/emoji_suggester_unittest.cc b/chrome/browser/chromeos/input_method/emoji_suggester_unittest.cc
index d3ef2a0..75ce680 100644
--- a/chrome/browser/chromeos/input_method/emoji_suggester_unittest.cc
+++ b/chrome/browser/chromeos/input_method/emoji_suggester_unittest.cc
@@ -80,12 +80,6 @@
   void OnSuggestionsChanged(
       const std::vector<std::string>& suggestions) override {}
 
-  bool ShowMultipleSuggestions(int context_id,
-                               const std::vector<base::string16>& candidates,
-                               std::string* error) override {
-    return false;
-  }
-
   void ClickButton(const ui::ime::AssistiveWindowButton& button) override {}
 
   bool AcceptSuggestionCandidate(int context_id,
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.cc b/chrome/browser/chromeos/input_method/input_method_engine.cc
index d765d76..cfe6b4f 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine.cc
@@ -137,25 +137,6 @@
   observer_->OnSuggestionsChanged(suggestions);
 }
 
-bool InputMethodEngine::ShowMultipleSuggestions(
-    int context_id,
-    const std::vector<base::string16>& suggestions,
-    std::string* error) {
-  if (!IsActive()) {
-    *error = kErrorNotActive;
-    return false;
-  }
-  if (context_id != context_id_ || context_id_ == -1) {
-    *error = kErrorWrongContext;
-    return false;
-  }
-  IMEAssistiveWindowHandlerInterface* aw_handler =
-      ui::IMEBridge::Get()->GetAssistiveWindowHandler();
-  if (aw_handler)
-    aw_handler->ShowMultipleSuggestions(suggestions);
-  return true;
-}
-
 bool InputMethodEngine::SetButtonHighlighted(
     int context_id,
     const ui::ime::AssistiveWindowButton& button,
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.h b/chrome/browser/chromeos/input_method/input_method_engine.h
index a772b3f..0068922 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine.h
+++ b/chrome/browser/chromeos/input_method/input_method_engine.h
@@ -118,10 +118,6 @@
   void OnSuggestionsChanged(
       const std::vector<std::string>& suggestions) override;
 
-  bool ShowMultipleSuggestions(int context_id,
-                               const std::vector<base::string16>& suggestions,
-                               std::string* error) override;
-
   bool SetButtonHighlighted(int context_id,
                             const ui::ime::AssistiveWindowButton& button,
                             bool highlighted,
diff --git a/chrome/browser/chromeos/input_method/native_input_method_engine.cc b/chrome/browser/chromeos/input_method/native_input_method_engine.cc
index 2bd949c4..c9b47291 100644
--- a/chrome/browser/chromeos/input_method/native_input_method_engine.cc
+++ b/chrome/browser/chromeos/input_method/native_input_method_engine.cc
@@ -65,6 +65,37 @@
   return modifier_state;
 }
 
+ime::mojom::InputFieldType TextInputTypeToMojoType(ui::TextInputType type) {
+  using ime::mojom::InputFieldType;
+  switch (type) {
+    case ui::TEXT_INPUT_TYPE_PASSWORD:
+      return InputFieldType::kPassword;
+    case ui::TEXT_INPUT_TYPE_SEARCH:
+      return InputFieldType::kSearch;
+    case ui::TEXT_INPUT_TYPE_EMAIL:
+      return InputFieldType::kEmail;
+    case ui::TEXT_INPUT_TYPE_TELEPHONE:
+      return InputFieldType::kTelephone;
+    case ui::TEXT_INPUT_TYPE_URL:
+      return InputFieldType::kURL;
+    case ui::TEXT_INPUT_TYPE_NUMBER:
+      return InputFieldType::kNumber;
+    case ui::TEXT_INPUT_TYPE_NULL:
+      return InputFieldType::kNoIME;
+    case ui::TEXT_INPUT_TYPE_TEXT:
+      return InputFieldType::kText;
+    default:
+      return InputFieldType::kText;
+  }
+}
+
+ime::mojom::AutocorrectMode AutocorrectFlagsToMojoType(int flags) {
+  if (flags & ui::TEXT_INPUT_FLAG_AUTOCORRECT_ON) {
+    return ime::mojom::AutocorrectMode::kEnabled;
+  }
+  return ime::mojom::AutocorrectMode::kDisabled;
+}
+
 enum class ImeServiceEvent {
   kUnknown = 0,
   kInitSuccess = 1,
@@ -177,7 +208,12 @@
 
   if (active_engine_id_ && ShouldUseFstMojoEngine(*active_engine_id_) &&
       remote_to_engine_.is_bound()) {
-    remote_to_engine_->OnFocus();
+    remote_to_engine_->OnFocus(ime::mojom::InputFieldInfo::New(
+        TextInputTypeToMojoType(context.type),
+        AutocorrectFlagsToMojoType(context.flags),
+        context.should_do_learning
+            ? ime::mojom::PersonalizationMode::kEnabled
+            : ime::mojom::PersonalizationMode::kDisabled));
   }
 
   base_observer_->OnFocus(context);
@@ -227,8 +263,12 @@
 
 void NativeInputMethodEngine::ImeObserver::OnReset(
     const std::string& engine_id) {
-  if (ShouldUseRuleBasedMojoEngine(engine_id) && remote_to_engine_.is_bound()) {
-    remote_to_engine_->ResetForRulebased();
+  if (remote_to_engine_.is_bound()) {
+    if (ShouldUseRuleBasedMojoEngine(engine_id)) {
+      remote_to_engine_->ResetForRulebased();
+    } else if (ShouldUseFstMojoEngine(engine_id)) {
+      remote_to_engine_->OnCompositionCanceled();
+    }
   }
   base_observer_->OnReset(engine_id);
 }
diff --git a/chrome/browser/chromeos/input_method/native_input_method_engine.h b/chrome/browser/chromeos/input_method/native_input_method_engine.h
index b0b51a5..6358e9f 100644
--- a/chrome/browser/chromeos/input_method/native_input_method_engine.h
+++ b/chrome/browser/chromeos/input_method/native_input_method_engine.h
@@ -92,12 +92,13 @@
     // mojom::InputChannel:
     void ProcessMessage(const std::vector<uint8_t>& message,
                         ProcessMessageCallback callback) override;
-    void OnFocus() override {}
+    void OnFocus(ime::mojom::InputFieldInfoPtr input_field_info) override {}
     void OnBlur() override {}
     void OnSurroundingTextChanged(
         const std::string& text,
         uint32_t offset,
         ime::mojom::SelectionRangePtr selection_range) override {}
+    void OnCompositionCanceled() override {}
     void ProcessKeypressForRulebased(
         ime::mojom::PhysicalKeyEventPtr event,
         ProcessKeypressForRulebasedCallback callback) override {}
diff --git a/chrome/browser/chromeos/input_method/personal_info_suggester_unittest.cc b/chrome/browser/chromeos/input_method/personal_info_suggester_unittest.cc
index 38b4f0a1..dafdbfd 100644
--- a/chrome/browser/chromeos/input_method/personal_info_suggester_unittest.cc
+++ b/chrome/browser/chromeos/input_method/personal_info_suggester_unittest.cc
@@ -71,12 +71,6 @@
     previous_suggestions_ = suggestions;
   }
 
-  bool ShowMultipleSuggestions(int context_id,
-                               const std::vector<base::string16>& candidates,
-                               std::string* error) override {
-    return false;
-  }
-
   void ClickButton(const ui::ime::AssistiveWindowButton& button) override {
     button_clicked_ = button.id;
   }
diff --git a/chrome/browser/chromeos/input_method/suggestion_handler_interface.h b/chrome/browser/chromeos/input_method/suggestion_handler_interface.h
index acd21445..ef3b299 100644
--- a/chrome/browser/chromeos/input_method/suggestion_handler_interface.h
+++ b/chrome/browser/chromeos/input_method/suggestion_handler_interface.h
@@ -39,11 +39,6 @@
   virtual void OnSuggestionsChanged(
       const std::vector<std::string>& suggestions) = 0;
 
-  virtual bool ShowMultipleSuggestions(
-      int context_id,
-      const std::vector<base::string16>& candidates,
-      std::string* error) = 0;
-
   // Highlights or unhighlights a given assistive button based on the given
   // parameters. No-op if context_id doesn't match or engine is not active.
   virtual bool SetButtonHighlighted(
diff --git a/chrome/browser/chromeos/policy/status_collector/app_info_generator.cc b/chrome/browser/chromeos/policy/status_collector/app_info_generator.cc
index e5b6f930..9986949 100644
--- a/chrome/browser/chromeos/policy/status_collector/app_info_generator.cc
+++ b/chrome/browser/chromeos/policy/status_collector/app_info_generator.cc
@@ -51,7 +51,7 @@
       return em::AppInfo::AppType::AppInfo_AppType_TYPE_WEB;
     case apps::mojom::AppType::kBorealis:
       return em::AppInfo::AppType::AppInfo_AppType_TYPE_BOREALIS;
-    case apps::mojom::AppType::kMacNative:
+    case apps::mojom::AppType::kMacOs:
     case apps::mojom::AppType::kLacros:
     case apps::mojom::AppType::kRemote:
     case apps::mojom::AppType::kUnknown:
diff --git a/chrome/browser/chromeos/web_applications/media_web_app_info.cc b/chrome/browser/chromeos/web_applications/media_web_app_info.cc
index 1d71c222..0bf30a1 100644
--- a/chrome/browser/chromeos/web_applications/media_web_app_info.cc
+++ b/chrome/browser/chromeos/web_applications/media_web_app_info.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/strings/string16.h"
+#include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chromeos/web_applications/system_web_app_install_utils.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
@@ -17,6 +18,38 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/l10n/l10n_util.h"
 
+namespace {
+
+// FileHandler configuration.
+// See https://github.com/WICG/file-handling/blob/master/explainer.md.
+constexpr std::tuple<const char*, const char*> kFileHandlers[] = {
+    {"image/*", ""},
+    {"video/*", ""},
+
+    // Raw images. Note the MIME type doesn't really matter here. MIME sniffing
+    // logic in the files app tends to detect image/tiff, but sniffing is only
+    // done for "local" files, so the extension list is needed in addition to
+    // the "image/*" wildcard above. The MIME type is never sent to the web app.
+    {"image/tiff", ".arw,.cr2,.dng,.nef,.nrw,.orf,.raf,.rw2"},
+};
+
+using AcceptMap = decltype(blink::Manifest::FileHandler::accept);
+
+// Converts the kFileHandlers constexpr into the std::map needed to populate the
+// web app manifest's `accept` property.
+AcceptMap MakeHandlerAccept() {
+  AcceptMap result;
+  const base::string16 separator = base::ASCIIToUTF16(",");
+  for (const auto& handler : kFileHandlers) {
+    result[base::ASCIIToUTF16(std::get<0>(handler))] =
+        base::SplitString(base::ASCIIToUTF16(std::get<1>(handler)), separator,
+                          base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
+  }
+  return result;
+}
+
+}  // namespace
+
 std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForMediaWebApp() {
   std::unique_ptr<WebApplicationInfo> info =
       std::make_unique<WebApplicationInfo>();
@@ -31,6 +64,7 @@
           {"app_icon_32.png", 32, IDR_MEDIA_APP_GALLERY_ICON_32_PNG},
           {"app_icon_48.png", 48, IDR_MEDIA_APP_GALLERY_ICON_48_PNG},
           {"app_icon_64.png", 64, IDR_MEDIA_APP_GALLERY_ICON_64_PNG},
+          {"app_icon_96.png", 96, IDR_MEDIA_APP_GALLERY_ICON_96_PNG},
           {"app_icon_128.png", 128, IDR_MEDIA_APP_GALLERY_ICON_128_PNG},
           {"app_icon_192.png", 192, IDR_MEDIA_APP_GALLERY_ICON_192_PNG},
           {"app_icon_256.png", 256, IDR_MEDIA_APP_GALLERY_ICON_256_PNG},
@@ -45,8 +79,7 @@
   blink::Manifest::FileHandler file_handler;
   file_handler.action = GURL(chromeos::kChromeUIMediaAppURL);
   file_handler.name = base::UTF8ToUTF16("Media File");
-  file_handler.accept[base::UTF8ToUTF16("image/*")] = {};
-  file_handler.accept[base::UTF8ToUTF16("video/*")] = {};
-  info->file_handlers.push_back(file_handler);
+  file_handler.accept = MakeHandlerAccept();
+  info->file_handlers.push_back(std::move(file_handler));
   return info;
 }
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/permission_item.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/permission_item.js
index b496834..acbaac9 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/permission_item.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/permission_item.js
@@ -29,6 +29,15 @@
     icon: String,
 
     /**
+     * If set to true, toggling the permission item will not set the permission
+     * in the backend. Call `syncPermission()` to set the permission to reflect
+     * the current UI state.
+     *
+     * @type {boolean}
+     */
+    syncPermissionManually: Boolean,
+
+    /**
      * @type {App}
      */
     app_: Object,
@@ -129,15 +138,17 @@
    * @private
    */
   togglePermission_() {
-    assert(this.app_);
-    // Plugin VM handles microphone and camera permissions manually.
-    // TODO(crbug:1071872): remove in m86 when plugin_vm permissions are
-    // updated.
-    if (this.app_.type == AppType.kPluginVm &&
-        (this.permissionType == 'MICROPHONE' ||
-         this.permissionType == 'CAMERA')) {
-      return;
+    if (!this.syncPermissionManually) {
+      this.syncPermission();
     }
+  },
+
+  /**
+   * Set the permission to match the current UI state. This only needs to be
+   * called when `syncPermissionManually` is set.
+   */
+  syncPermission() {
+    assert(this.app_);
 
     /** @type {!Permission} */
     let newPermission;
@@ -148,12 +159,12 @@
                 .valueType) {
       case PermissionValueType.kBool:
         newPermission =
-            this.getNewPermissionBoolean_(this.app_, this.permissionType);
+            this.getUIPermissionBoolean_(this.app_, this.permissionType);
         newBoolState = newPermission.value === Bool.kTrue;
         break;
       case PermissionValueType.kTriState:
         newPermission =
-            this.getNewPermissionTriState_(this.app_, this.permissionType);
+            this.getUIPermissionTriState_(this.app_, this.permissionType);
         newBoolState = newPermission.value === TriState.kAllow;
         break;
       default:
@@ -171,12 +182,14 @@
   },
 
   /**
+   * Gets the permission boolean based on the toggle's UI state.
+   *
    * @param {App} app
    * @param {string} permissionType
    * @return {!Permission}
    * @private
    */
-  getNewPermissionBoolean_(app, permissionType) {
+  getUIPermissionBoolean_(app, permissionType) {
     let newPermissionValue;
     const currentPermission =
         app_management.util.getPermission(app, permissionType);
@@ -200,12 +213,14 @@
   },
 
   /**
+   * Gets the permission tristate based on the toggle's UI state.
+   *
    * @param {App} app
    * @param {string} permissionType
    * @return {!Permission}
    * @private
    */
-  getNewPermissionTriState_(app, permissionType) {
+  getUIPermissionTriState_(app, permissionType) {
     let newPermissionValue;
     const currentPermission =
         app_management.util.getPermission(app, permissionType);
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html
index 7d015ff..87d7c5e4 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html
@@ -30,6 +30,7 @@
             <app-management-permission-item
                 id="camera-permission"
                 class="subpermission-row" icon="app-management:camera"
+                sync-permission-manually
                 permission-label="$i18n{appManagementCameraPermissionLabel}"
                 permission-type="CAMERA"
                 on-change="onPermissionChanged_">
@@ -39,6 +40,7 @@
             <app-management-permission-item
                 id="microphone-permission"
                 class="subpermission-row" icon="app-management:microphone"
+                sync-permission-manually
                 permission-label="$i18n{appManagementMicrophonePermissionLabel}"
                 permission-type="MICROPHONE"
                 on-change="onPermissionChanged_">
diff --git a/chrome/browser/sync/test/integration/single_client_extensions_sync_test.cc b/chrome/browser/sync/test/integration/single_client_extensions_sync_test.cc
index b570b9f..deb79911 100644
--- a/chrome/browser/sync/test/integration/single_client_extensions_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_extensions_sync_test.cc
@@ -36,9 +36,8 @@
   ASSERT_TRUE(AllProfilesHaveSameExtensionsAsVerifier());
 }
 
-// Flaky: https://crbug.com/1030556
 IN_PROC_BROWSER_TEST_F(SingleClientExtensionsSyncTest,
-                       DISABLED_StartWithSomeExtensions) {
+                       StartWithSomeExtensions) {
   ASSERT_TRUE(SetupClients());
 
   const int kNumExtensions = 5;
diff --git a/chrome/browser/ui/android/native_page/BUILD.gn b/chrome/browser/ui/android/native_page/BUILD.gn
index 85cfe3c..01c80a96 100644
--- a/chrome/browser/ui/android/native_page/BUILD.gn
+++ b/chrome/browser/ui/android/native_page/BUILD.gn
@@ -13,8 +13,6 @@
   deps = [
     "//base:base_java",
     "//components/browser_ui/styles/android:java",
-    "//components/embedder_support/android:util_java",
     "//content/public/android:content_java",
-    "//third_party/android_deps:androidx_annotation_annotation_java",
   ]
 }
diff --git a/chrome/browser/ui/android/native_page/DEPS b/chrome/browser/ui/android/native_page/DEPS
index 78dd1a2..2d0aef2 100644
--- a/chrome/browser/ui/android/native_page/DEPS
+++ b/chrome/browser/ui/android/native_page/DEPS
@@ -2,6 +2,5 @@
 include_rules = [
   "+base/android",
   "+components/browser_ui/styles/android",
-  "+components/embedder_support/android",
   "+content/public/android",
 ]
diff --git a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java b/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java
index 93a97756..49add778 100644
--- a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java
+++ b/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java
@@ -4,16 +4,8 @@
 
 package org.chromium.chrome.browser.ui.native_page;
 
-import android.net.Uri;
 import android.view.View;
 
-import androidx.annotation.IntDef;
-
-import org.chromium.components.embedder_support.util.UrlConstants;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 /**
  * An interface for pages that will be using Android views instead of html/rendered Web content.
  */
@@ -64,69 +56,4 @@
      * Called after a page has been removed from the view hierarchy and will no longer be used.
      */
     void destroy();
-
-    @IntDef({NativePageType.NONE, NativePageType.CANDIDATE, NativePageType.NTP,
-            NativePageType.BOOKMARKS, NativePageType.RECENT_TABS, NativePageType.DOWNLOADS,
-            NativePageType.HISTORY, NativePageType.EXPLORE})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface NativePageType {
-        int NONE = 0;
-        int CANDIDATE = 1;
-        int NTP = 2;
-        int BOOKMARKS = 3;
-        int RECENT_TABS = 4;
-        int DOWNLOADS = 5;
-        int HISTORY = 6;
-        int EXPLORE = 7;
-    }
-
-    /**
-     * Returns whether the URL would navigate to a native page.
-     *
-     * @param url The URL to be checked.
-     * @param isIncognito Whether the page will be displayed in incognito mode.
-     * @return Whether the host and the scheme of the passed in URL matches one of the supported
-     *         native pages.
-     */
-    public static boolean isNativePageUrl(String url, boolean isIncognito) {
-        return nativePageType(url, null, isIncognito) != NativePageType.NONE;
-    }
-
-    /**
-     * @param url The URL to be checked.
-     * @param candidatePage NativePage to return as result if the host is matched.
-     * @param isIncognito Whether the page will be displayed in incognito mode.
-     * @return Type of the native page defined in {@link NativePageType}.
-     */
-    public static @NativePageType int nativePageType(
-            String url, NativePage candidatePage, boolean isIncognito) {
-        if (url == null) return NativePageType.NONE;
-
-        Uri uri = Uri.parse(url);
-        if (!UrlConstants.CHROME_NATIVE_SCHEME.equals(uri.getScheme())
-                && !UrlConstants.CHROME_SCHEME.equals(uri.getScheme())) {
-            return NativePageType.NONE;
-        }
-
-        String host = uri.getHost();
-        if (candidatePage != null && candidatePage.getHost().equals(host)) {
-            return NativePageType.CANDIDATE;
-        }
-
-        if (UrlConstants.NTP_HOST.equals(host)) {
-            return NativePageType.NTP;
-        } else if (UrlConstants.BOOKMARKS_HOST.equals(host)) {
-            return NativePageType.BOOKMARKS;
-        } else if (UrlConstants.DOWNLOADS_HOST.equals(host)) {
-            return NativePageType.DOWNLOADS;
-        } else if (UrlConstants.HISTORY_HOST.equals(host)) {
-            return NativePageType.HISTORY;
-        } else if (UrlConstants.RECENT_TABS_HOST.equals(host) && !isIncognito) {
-            return NativePageType.RECENT_TABS;
-        } else if (UrlConstants.EXPLORE_HOST.equals(host)) {
-            return NativePageType.EXPLORE;
-        } else {
-            return NativePageType.NONE;
-        }
-    }
 }
diff --git a/chrome/browser/ui/app_list/search/app_service_app_result.cc b/chrome/browser/ui/app_list/search/app_service_app_result.cc
index 07c0dadb..a86b605 100644
--- a/chrome/browser/ui/app_list/search/app_service_app_result.cc
+++ b/chrome/browser/ui/app_list/search/app_service_app_result.cc
@@ -125,7 +125,7 @@
       return ash::REMOTE_APP;
     case apps::mojom::AppType::kBorealis:
       return ash::BOREALIS_APP;
-    case apps::mojom::AppType::kMacNative:
+    case apps::mojom::AppType::kMacOs:
     case apps::mojom::AppType::kUnknown:
       NOTREACHED();
       return ash::SEARCH_RESULT_TYPE_BOUNDARY;
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_shelf_context_menu.cc b/chrome/browser/ui/ash/launcher/app_service/app_service_shelf_context_menu.cc
index 3c7043f..b593be9 100644
--- a/chrome/browser/ui/ash/launcher/app_service/app_service_shelf_context_menu.cc
+++ b/chrome/browser/ui/ash/launcher/app_service/app_service_shelf_context_menu.cc
@@ -552,7 +552,7 @@
       // Type kUnknown is used for "unregistered" Crostini apps, which do not
       // have a .desktop file and can only be closed, not pinned.
       return false;
-    case apps::mojom::AppType::kMacNative:
+    case apps::mojom::AppType::kMacOs:
     case apps::mojom::AppType::kRemote:
     case apps::mojom::AppType::kBorealis:
       NOTREACHED() << "Type " << app_type_ << " should not appear in shelf.";
diff --git a/chrome/browser/ui/intent_picker_tab_helper.cc b/chrome/browser/ui/intent_picker_tab_helper.cc
index 105de622..1e6749c 100644
--- a/chrome/browser/ui/intent_picker_tab_helper.cc
+++ b/chrome/browser/ui/intent_picker_tab_helper.cc
@@ -32,7 +32,7 @@
       app_type = apps::mojom::AppType::kWeb;
       break;
     case apps::PickerEntryType::kMacOs:
-      app_type = apps::mojom::AppType::kMacNative;
+      app_type = apps::mojom::AppType::kMacOs;
       break;
   }
   return app_type;
diff --git a/chrome/browser/ui/startup/automation_infobar_delegate.cc b/chrome/browser/ui/startup/automation_infobar_delegate.cc
index 1bb1e31..e499b948 100644
--- a/chrome/browser/ui/startup/automation_infobar_delegate.cc
+++ b/chrome/browser/ui/startup/automation_infobar_delegate.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/ui/startup/automation_infobar_delegate.h"
 
+#include <memory>
+#include <utility>
+
 #include "chrome/browser/devtools/global_confirm_info_bar.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/grit/generated_resources.h"
@@ -17,10 +20,6 @@
   GlobalConfirmInfoBar::Show(std::move(delegate));
 }
 
-AutomationInfoBarDelegate::AutomationInfoBarDelegate() {}
-
-AutomationInfoBarDelegate::~AutomationInfoBarDelegate() {}
-
 infobars::InfoBarDelegate::InfoBarIdentifier
 AutomationInfoBarDelegate::GetIdentifier() const {
   return AUTOMATION_INFOBAR_DELEGATE;
diff --git a/chrome/browser/ui/startup/automation_infobar_delegate.h b/chrome/browser/ui/startup/automation_infobar_delegate.h
index f8f43c4..315bd63 100644
--- a/chrome/browser/ui/startup/automation_infobar_delegate.h
+++ b/chrome/browser/ui/startup/automation_infobar_delegate.h
@@ -6,7 +6,6 @@
 #define CHROME_BROWSER_UI_STARTUP_AUTOMATION_INFOBAR_DELEGATE_H_
 
 #include "base/compiler_specific.h"
-#include "base/macros.h"
 #include "base/strings/string16.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "url/gurl.h"
@@ -16,18 +15,19 @@
 class AutomationInfoBarDelegate : public ConfirmInfoBarDelegate {
  public:
   static void Create();
+  AutomationInfoBarDelegate(const AutomationInfoBarDelegate&) = delete;
+  AutomationInfoBarDelegate& operator=(const AutomationInfoBarDelegate&) =
+      delete;
 
  private:
-  AutomationInfoBarDelegate();
-  ~AutomationInfoBarDelegate() override;
+  AutomationInfoBarDelegate() = default;
+  ~AutomationInfoBarDelegate() override = default;
 
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
   bool ShouldExpire(const NavigationDetails& details) const override;
   bool ShouldAnimate() const override;
   base::string16 GetMessageText() const override;
   int GetButtons() const override;
-
-  DISALLOW_COPY_AND_ASSIGN(AutomationInfoBarDelegate);
 };
 
 #endif  // CHROME_BROWSER_UI_STARTUP_AUTOMATION_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/ui/startup/credential_provider_signin_dialog_win.cc b/chrome/browser/ui/startup/credential_provider_signin_dialog_win.cc
index fdc0658d..07911436 100644
--- a/chrome/browser/ui/startup/credential_provider_signin_dialog_win.cc
+++ b/chrome/browser/ui/startup/credential_provider_signin_dialog_win.cc
@@ -147,6 +147,11 @@
       : signin_callback_(std::move(signin_callback)),
         additional_mdm_oauth_scopes_(additional_mdm_oauth_scopes) {}
 
+  CredentialProviderWebUIMessageHandler(
+      const CredentialProviderWebUIMessageHandler&) = delete;
+  CredentialProviderWebUIMessageHandler& operator=(
+      const CredentialProviderWebUIMessageHandler&) = delete;
+
   // content::WebUIMessageHandler:
   void RegisterMessages() override {
     web_ui()->RegisterMessageCallback(
@@ -249,8 +254,6 @@
 
   HandleGcpwSigninCompleteResult signin_callback_;
   const std::string additional_mdm_oauth_scopes_;
-
-  DISALLOW_COPY_AND_ASSIGN(CredentialProviderWebUIMessageHandler);
 };
 
 }  // namespace
@@ -280,6 +283,11 @@
         show_tos_(show_tos),
         signin_callback_(std::move(signin_callback)) {}
 
+  CredentialProviderWebDialogDelegate(
+      const CredentialProviderWebDialogDelegate&) = delete;
+  CredentialProviderWebDialogDelegate& operator=(
+      const CredentialProviderWebDialogDelegate&) = delete;
+
   GURL GetDialogContentURL() const override {
     signin_metrics::AccessPoint access_point =
         signin_metrics::AccessPoint::ACCESS_POINT_MACHINE_LOGON;
@@ -403,9 +411,6 @@
   mutable HandleGcpwSigninCompleteResult signin_callback_;
 
   mutable CredentialProviderWebUIMessageHandler* handler_ = nullptr;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CredentialProviderWebDialogDelegate);
 };
 
 bool ValidateSigninCompleteResult(const std::string& access_token,
diff --git a/chrome/browser/ui/startup/credential_provider_signin_dialog_win_browsertest.cc b/chrome/browser/ui/startup/credential_provider_signin_dialog_win_browsertest.cc
index e4252a5..c531a64c 100644
--- a/chrome/browser/ui/startup/credential_provider_signin_dialog_win_browsertest.cc
+++ b/chrome/browser/ui/startup/credential_provider_signin_dialog_win_browsertest.cc
@@ -41,6 +41,12 @@
 };
 
 class CredentialProviderSigninDialogWinBaseTest : public InProcessBrowserTest {
+ public:
+  CredentialProviderSigninDialogWinBaseTest(
+      const CredentialProviderSigninDialogWinBaseTest&) = delete;
+  CredentialProviderSigninDialogWinBaseTest& operator=(
+      const CredentialProviderSigninDialogWinBaseTest&) = delete;
+
  protected:
   CredentialProviderSigninDialogWinBaseTest();
 
@@ -49,9 +55,6 @@
 
   views::WebDialogView* web_view_ = nullptr;
   content::WebContents* web_contents_ = nullptr;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CredentialProviderSigninDialogWinBaseTest);
 };
 
 CredentialProviderSigninDialogWinBaseTest::
@@ -74,6 +77,12 @@
 
 class CredentialProviderSigninDialogWinDialogTest
     : public CredentialProviderSigninDialogWinBaseTest {
+ public:
+  CredentialProviderSigninDialogWinDialogTest(
+      const CredentialProviderSigninDialogWinDialogTest&) = delete;
+  CredentialProviderSigninDialogWinDialogTest& operator=(
+      const CredentialProviderSigninDialogWinDialogTest&) = delete;
+
  protected:
   CredentialProviderSigninDialogWinDialogTest();
 
@@ -100,8 +109,6 @@
 
  private:
   base::OnceClosure signin_complete_closure_;
-
-  DISALLOW_COPY_AND_ASSIGN(CredentialProviderSigninDialogWinDialogTest);
 };
 
 CredentialProviderSigninDialogWinDialogTest::
@@ -361,8 +368,8 @@
   base::Value signin_result = test_data_storage_.MakeValidSignInResponseValue();
 
   int expected_error_code = GetParam();
-  bool should_succeed =
-      expected_error_code == (int)credential_provider::kUiecSuccess;
+  bool should_succeed = expected_error_code ==
+                        static_cast<int>(credential_provider::kUiecSuccess);
   signin_result.SetKey(credential_provider::kKeyExitCode,
                        base::Value(expected_error_code));
 
@@ -418,14 +425,16 @@
 
 class CredentialProviderSigninDialogWinIntegrationTestBase
     : public CredentialProviderSigninDialogWinBaseTest {
+ public:
+  CredentialProviderSigninDialogWinIntegrationTestBase(
+      const CredentialProviderSigninDialogWinIntegrationTestBase&) = delete;
+  CredentialProviderSigninDialogWinIntegrationTestBase& operator=(
+      const CredentialProviderSigninDialogWinIntegrationTestBase&) = delete;
+
  protected:
   CredentialProviderSigninDialogWinIntegrationTestBase();
   // InProcessBrowserTest:
   void SetUpCommandLine(base::CommandLine* command_line) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(
-      CredentialProviderSigninDialogWinIntegrationTestBase);
 };
 
 CredentialProviderSigninDialogWinIntegrationTestBase::
@@ -441,12 +450,17 @@
 // Chrome will not be running on Winlogon desktop.
 class CredentialProviderSigninDialogWinIntegrationDesktopVerificationTest
     : public CredentialProviderSigninDialogWinIntegrationTestBase {
+ public:
+  CredentialProviderSigninDialogWinIntegrationDesktopVerificationTest(
+      const CredentialProviderSigninDialogWinIntegrationDesktopVerificationTest&) =
+      delete;
+  CredentialProviderSigninDialogWinIntegrationDesktopVerificationTest&
+  operator=(
+      const CredentialProviderSigninDialogWinIntegrationDesktopVerificationTest&) =
+      delete;
+
  protected:
   CredentialProviderSigninDialogWinIntegrationDesktopVerificationTest();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(
-      CredentialProviderSigninDialogWinIntegrationDesktopVerificationTest);
 };
 
 CredentialProviderSigninDialogWinIntegrationDesktopVerificationTest::
@@ -471,16 +485,20 @@
 // be displayed even when not running on Winlogon desktop.
 class CredentialProviderSigninDialogWinIntegrationDialogDisplayTest
     : public CredentialProviderSigninDialogWinIntegrationTestBase {
+ public:
+  CredentialProviderSigninDialogWinIntegrationDialogDisplayTest(
+      const CredentialProviderSigninDialogWinIntegrationDialogDisplayTest&) =
+      delete;
+  CredentialProviderSigninDialogWinIntegrationDialogDisplayTest& operator=(
+      const CredentialProviderSigninDialogWinIntegrationDialogDisplayTest&) =
+      delete;
+
  protected:
   CredentialProviderSigninDialogWinIntegrationDialogDisplayTest();
   ~CredentialProviderSigninDialogWinIntegrationDialogDisplayTest() override;
 
   // CredentialProviderSigninDialogWinBaseTest:
   void WaitForDialogToLoad() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(
-      CredentialProviderSigninDialogWinIntegrationDialogDisplayTest);
 };
 
 CredentialProviderSigninDialogWinIntegrationDialogDisplayTest::
@@ -521,8 +539,8 @@
     CredentialProviderSigninDialogWinIntegrationDialogDisplayTest,
     ShowDialogOnlyTest) {
   WaitForDialogToLoad();
-  EXPECT_TRUE(
-      ((Profile*)(web_contents_->GetBrowserContext()))->IsIncognitoProfile());
+  EXPECT_TRUE(reinterpret_cast<Profile*>(web_contents_->GetBrowserContext())
+                  ->IsIncognitoProfile());
   views::Widget::Widgets all_widgets = views::test::WidgetTest::GetAllWidgets();
   (*all_widgets.begin())->Close();
   RunUntilBrowserProcessQuits();
diff --git a/chrome/browser/ui/startup/credential_provider_signin_info_fetcher_win.cc b/chrome/browser/ui/startup/credential_provider_signin_info_fetcher_win.cc
index 4b6dedf..6516a76 100644
--- a/chrome/browser/ui/startup/credential_provider_signin_info_fetcher_win.cc
+++ b/chrome/browser/ui/startup/credential_provider_signin_info_fetcher_win.cc
@@ -2,6 +2,7 @@
 // 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>
 
diff --git a/chrome/browser/ui/startup/credential_provider_signin_info_fetcher_win.h b/chrome/browser/ui/startup/credential_provider_signin_info_fetcher_win.h
index 421ec8b..e5ed5de 100644
--- a/chrome/browser/ui/startup/credential_provider_signin_info_fetcher_win.h
+++ b/chrome/browser/ui/startup/credential_provider_signin_info_fetcher_win.h
@@ -8,7 +8,6 @@
 #include <string>
 
 #include "base/callback.h"
-#include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/values.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
@@ -42,6 +41,10 @@
   CredentialProviderSigninInfoFetcher(
       const std::string& refresh_token,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+  CredentialProviderSigninInfoFetcher(
+      const CredentialProviderSigninInfoFetcher&) = delete;
+  CredentialProviderSigninInfoFetcher& operator=(
+      const CredentialProviderSigninInfoFetcher&) = delete;
   ~CredentialProviderSigninInfoFetcher() override;
 
   void SetCompletionCallbackAndStart(
@@ -78,8 +81,6 @@
   std::unique_ptr<OAuth2AccessTokenFetcher> scoped_access_token_fetcher_;
   std::unique_ptr<gaia::GaiaOAuthClient> user_info_fetcher_;
   std::unique_ptr<gaia::GaiaOAuthClient> token_handle_fetcher_;
-
-  DISALLOW_COPY_AND_ASSIGN(CredentialProviderSigninInfoFetcher);
 };
 
 #endif  // CHROME_BROWSER_UI_STARTUP_CREDENTIAL_PROVIDER_SIGNIN_INFO_FETCHER_WIN_H_
diff --git a/chrome/browser/ui/startup/credential_provider_signin_info_fetcher_win_unittest.cc b/chrome/browser/ui/startup/credential_provider_signin_info_fetcher_win_unittest.cc
index 1111420..a7d0f37 100644
--- a/chrome/browser/ui/startup/credential_provider_signin_info_fetcher_win_unittest.cc
+++ b/chrome/browser/ui/startup/credential_provider_signin_info_fetcher_win_unittest.cc
@@ -7,10 +7,11 @@
 #include "chrome/browser/ui/startup/credential_provider_signin_dialog_win_test_data.h"
 
 #include <string>
+#include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/json/json_reader.h"
-#include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/test/bind_test_util.h"
@@ -38,6 +39,9 @@
 class CredentialProviderFetcherTest : public ::testing::Test {
  protected:
   CredentialProviderFetcherTest();
+  CredentialProviderFetcherTest(const CredentialProviderFetcherTest&) = delete;
+  CredentialProviderFetcherTest& operator=(
+      const CredentialProviderFetcherTest&) = delete;
   ~CredentialProviderFetcherTest() override;
 
   void OnFetchComplete(base::OnceClosure done_closure,
@@ -71,8 +75,6 @@
 
  private:
   scoped_refptr<network::SharedURLLoaderFactory> shared_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CredentialProviderFetcherTest);
 };
 
 CredentialProviderFetcherTest::CredentialProviderFetcherTest()
diff --git a/chrome/browser/ui/startup/default_browser_infobar_delegate.cc b/chrome/browser/ui/startup/default_browser_infobar_delegate.cc
index 2bc1ed3..35c1dd1 100644
--- a/chrome/browser/ui/startup/default_browser_infobar_delegate.cc
+++ b/chrome/browser/ui/startup/default_browser_infobar_delegate.cc
@@ -28,10 +28,7 @@
 }
 
 DefaultBrowserInfoBarDelegate::DefaultBrowserInfoBarDelegate(Profile* profile)
-    : ConfirmInfoBarDelegate(),
-      profile_(profile),
-      should_expire_(false),
-      action_taken_(false) {
+    : profile_(profile) {
   // We want the info-bar to stick-around for few seconds and then be hidden
   // on the next navigation after that.
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
diff --git a/chrome/browser/ui/startup/default_browser_infobar_delegate.h b/chrome/browser/ui/startup/default_browser_infobar_delegate.h
index 6523cb8..4f830257 100644
--- a/chrome/browser/ui/startup/default_browser_infobar_delegate.h
+++ b/chrome/browser/ui/startup/default_browser_infobar_delegate.h
@@ -22,6 +22,10 @@
   // |infobar_service|.
   static void Create(InfoBarService* infobar_service, Profile* profile);
 
+  DefaultBrowserInfoBarDelegate(const DefaultBrowserInfoBarDelegate&) = delete;
+  DefaultBrowserInfoBarDelegate& operator=(
+      const DefaultBrowserInfoBarDelegate&) = delete;
+
  protected:
   explicit DefaultBrowserInfoBarDelegate(Profile* profile);
   ~DefaultBrowserInfoBarDelegate() override;
@@ -58,15 +62,13 @@
   Profile* profile_;
 
   // Whether the info bar should be dismissed on the next navigation.
-  bool should_expire_;
+  bool should_expire_ = false;
 
   // Indicates if the user interacted with the infobar.
-  bool action_taken_;
+  bool action_taken_ = false;
 
   // Used to delay the expiration of the info-bar.
   base::WeakPtrFactory<DefaultBrowserInfoBarDelegate> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(DefaultBrowserInfoBarDelegate);
 };
 
 }  // namespace chrome
diff --git a/chrome/browser/ui/startup/google_api_keys_infobar_delegate.cc b/chrome/browser/ui/startup/google_api_keys_infobar_delegate.cc
index f2d4a63..8739623 100644
--- a/chrome/browser/ui/startup/google_api_keys_infobar_delegate.cc
+++ b/chrome/browser/ui/startup/google_api_keys_infobar_delegate.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/startup/google_api_keys_infobar_delegate.h"
 
+#include <memory>
+
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/grit/chromium_strings.h"
 #include "components/infobars/core/infobar.h"
@@ -23,9 +25,6 @@
     : ConfirmInfoBarDelegate() {
 }
 
-GoogleApiKeysInfoBarDelegate::~GoogleApiKeysInfoBarDelegate() {
-}
-
 infobars::InfoBarDelegate::InfoBarIdentifier
 GoogleApiKeysInfoBarDelegate::GetIdentifier() const {
   return GOOGLE_API_KEYS_INFOBAR_DELEGATE;
diff --git a/chrome/browser/ui/startup/google_api_keys_infobar_delegate.h b/chrome/browser/ui/startup/google_api_keys_infobar_delegate.h
index deb839a..00b388f3 100644
--- a/chrome/browser/ui/startup/google_api_keys_infobar_delegate.h
+++ b/chrome/browser/ui/startup/google_api_keys_infobar_delegate.h
@@ -5,8 +5,6 @@
 #ifndef CHROME_BROWSER_UI_STARTUP_GOOGLE_API_KEYS_INFOBAR_DELEGATE_H_
 #define CHROME_BROWSER_UI_STARTUP_GOOGLE_API_KEYS_INFOBAR_DELEGATE_H_
 
-#include "base/compiler_specific.h"
-#include "base/macros.h"
 #include "base/strings/string16.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "url/gurl.h"
@@ -20,17 +18,19 @@
   // to |infobar_service|.
   static void Create(InfoBarService* infobar_service);
 
+  GoogleApiKeysInfoBarDelegate(const GoogleApiKeysInfoBarDelegate&) = delete;
+  GoogleApiKeysInfoBarDelegate& operator=(const GoogleApiKeysInfoBarDelegate&) =
+      delete;
+
  private:
   GoogleApiKeysInfoBarDelegate();
-  ~GoogleApiKeysInfoBarDelegate() override;
+  ~GoogleApiKeysInfoBarDelegate() override = default;
 
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
   base::string16 GetLinkText() const override;
   GURL GetLinkURL() const override;
   base::string16 GetMessageText() const override;
   int GetButtons() const override;
-
-  DISALLOW_COPY_AND_ASSIGN(GoogleApiKeysInfoBarDelegate);
 };
 
 #endif  // CHROME_BROWSER_UI_STARTUP_GOOGLE_API_KEYS_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/ui/startup/invalid_user_data_dir_interactive_uitest.cc b/chrome/browser/ui/startup/invalid_user_data_dir_interactive_uitest.cc
index 99ed227..fbe42423 100644
--- a/chrome/browser/ui/startup/invalid_user_data_dir_interactive_uitest.cc
+++ b/chrome/browser/ui/startup/invalid_user_data_dir_interactive_uitest.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/macros.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/simple_message_box_internal.h"
 #include "chrome/common/chrome_paths.h"
@@ -12,8 +11,10 @@
 // https://crbug.com/833624
 class InvalidUserDataDirTest : public InProcessBrowserTest {
  public:
-  InvalidUserDataDirTest() {}
-  ~InvalidUserDataDirTest() override {}
+  InvalidUserDataDirTest() = default;
+  InvalidUserDataDirTest(const InvalidUserDataDirTest&) = delete;
+  InvalidUserDataDirTest& operator=(const InvalidUserDataDirTest&) = delete;
+  ~InvalidUserDataDirTest() override = default;
 
  private:
   void SetUp() override {
@@ -28,8 +29,6 @@
   // browser initialization, the screen is not set until after the call to
   // chrome::GetInvalidSpecifiedUserDataDir.
   void SetScreenInstance() override {}
-
-  DISALLOW_COPY_AND_ASSIGN(InvalidUserDataDirTest);
 };
 
 IN_PROC_BROWSER_TEST_F(InvalidUserDataDirTest, Basic) {
diff --git a/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc b/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc
index f460e2a80..cec50cc 100644
--- a/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc
+++ b/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/startup/obsolete_system_infobar_delegate.h"
 
+#include <memory>
+
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/obsolete_system/obsolete_system.h"
 #include "components/infobars/core/infobar.h"
@@ -21,9 +23,6 @@
     : ConfirmInfoBarDelegate() {
 }
 
-ObsoleteSystemInfoBarDelegate::~ObsoleteSystemInfoBarDelegate() {
-}
-
 infobars::InfoBarDelegate::InfoBarIdentifier
 ObsoleteSystemInfoBarDelegate::GetIdentifier() const {
   return OBSOLETE_SYSTEM_INFOBAR_DELEGATE;
diff --git a/chrome/browser/ui/startup/obsolete_system_infobar_delegate.h b/chrome/browser/ui/startup/obsolete_system_infobar_delegate.h
index ef7a0714..920749d1 100644
--- a/chrome/browser/ui/startup/obsolete_system_infobar_delegate.h
+++ b/chrome/browser/ui/startup/obsolete_system_infobar_delegate.h
@@ -5,8 +5,6 @@
 #ifndef CHROME_BROWSER_UI_STARTUP_OBSOLETE_SYSTEM_INFOBAR_DELEGATE_H_
 #define CHROME_BROWSER_UI_STARTUP_OBSOLETE_SYSTEM_INFOBAR_DELEGATE_H_
 
-#include "base/compiler_specific.h"
-#include "base/macros.h"
 #include "base/strings/string16.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "url/gurl.h"
@@ -21,9 +19,13 @@
   // |infobar_service|.
   static void Create(InfoBarService* infobar_service);
 
+  ObsoleteSystemInfoBarDelegate(const ObsoleteSystemInfoBarDelegate&) = delete;
+  ObsoleteSystemInfoBarDelegate& operator=(
+      const ObsoleteSystemInfoBarDelegate&) = delete;
+
  private:
   ObsoleteSystemInfoBarDelegate();
-  ~ObsoleteSystemInfoBarDelegate() override;
+  ~ObsoleteSystemInfoBarDelegate() override = default;
 
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
   base::string16 GetLinkText() const override;
@@ -31,8 +33,6 @@
   base::string16 GetMessageText() const override;
   int GetButtons() const override;
   bool ShouldExpire(const NavigationDetails& details) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(ObsoleteSystemInfoBarDelegate);
 };
 
 #endif  // CHROME_BROWSER_UI_STARTUP_OBSOLETE_SYSTEM_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc
index 295cdff..cf46cfa8 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -18,7 +18,6 @@
 #include "base/files/file_util.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_base.h"
 #include "base/metrics/histogram_functions.h"
@@ -100,7 +99,9 @@
 #if defined(OS_WIN)
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/metrics/jumplist_metrics_win.h"
+#include "chrome/browser/notifications/notification_platform_bridge_win.h"
 #include "chrome/browser/notifications/win/notification_launch_id.h"
+#include "chrome/browser/ui/startup/credential_provider_signin_dialog_win.h"
 #include "chrome/browser/ui/webui/settings/reset_settings_handler.h"
 #include "chrome/credential_provider/common/gcp_strings.h"
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
@@ -122,7 +123,8 @@
                               public BrowserListObserver {
  public:
   ProfileLaunchObserver() { BrowserList::AddObserver(this); }
-
+  ProfileLaunchObserver(const ProfileLaunchObserver&) = delete;
+  ProfileLaunchObserver& operator=(const ProfileLaunchObserver&) = delete;
   ~ProfileLaunchObserver() override { BrowserList::RemoveObserver(this); }
 
   // BrowserListObserver:
@@ -226,8 +228,6 @@
   // Set once we attempted to activate a profile. We only get one shot at this.
   bool activated_profile_ = false;
   ScopedObserver<Profile, ProfileObserver> observed_profiles_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ProfileLaunchObserver);
 };
 
 base::LazyInstance<ProfileLaunchObserver>::DestructorAtExit
@@ -413,6 +413,10 @@
     chrome::startup::IsFirstRun is_first_run,
     std::unique_ptr<LaunchModeRecorder> launch_mode_recorder) {
   DCHECK(profile);
+#if defined(OS_WIN)
+  DCHECK(!command_line.HasSwitch(credential_provider::kGcpwSigninSwitch));
+  DCHECK(!command_line.HasSwitch(switches::kNotificationLaunchId));
+#endif  // defined(OS_WIN)
   in_synchronous_profile_launch_ =
       process_startup == chrome::startup::IS_PROCESS_STARTUP;
 
@@ -433,12 +437,6 @@
       profile = profile->GetPrimaryOTRProfile();
   }
 
-#if defined(OS_WIN)
-  // Continue with the incognito profile if this is a credential provider logon.
-  if (command_line.HasSwitch(credential_provider::kGcpwSigninSwitch))
-    profile = profile->GetPrimaryOTRProfile();
-#endif
-
   if (!IsSilentLaunchEnabled(command_line, profile)) {
     StartupBrowserCreatorImpl lwp(cur_dir, command_line, this, is_first_run);
     const std::vector<GURL> urls_to_launch =
@@ -854,6 +852,35 @@
         chrome::kJumpListIconDirname,
         base::WrapUnique(new base::SupportsUserData::Data()));
   }
+
+  // If the command line has the kNotificationLaunchId switch, then this
+  // call is from notification_helper.exe to process toast activation.
+  // Delegate to the notification system; do not open a browser window here.
+  if (command_line.HasSwitch(switches::kNotificationLaunchId)) {
+    if (NotificationPlatformBridgeWin::HandleActivation(command_line)) {
+      LaunchModeRecorder().SetLaunchMode(LaunchMode::kWinPlatformNotification);
+      return true;
+    }
+    return false;
+  }
+
+  // If being started for credential provider logon purpose, only show the
+  // signin page.
+  if (command_line.HasSwitch(credential_provider::kGcpwSigninSwitch)) {
+    // Use incognito profile since this is a credential provider logon.
+    Profile* profile = last_used_profile->GetPrimaryOTRProfile();
+    DCHECK(profile->IsIncognitoProfile());
+    // NOTE: All launch urls are ignored when running with --gcpw-signin since
+    // this mode only loads Google's sign in page.
+
+    // If GCPW signin dialog fails, returning false here will allow Chrome to
+    // exit gracefully during the launch.
+    if (!StartGCPWSignin(command_line, profile))
+      return false;
+
+    LaunchModeRecorder().SetLaunchMode(LaunchMode::kCredentialProviderSignIn);
+    return true;
+  }
 #endif  // defined(OS_WIN)
 
   return LaunchBrowserForLastProfiles(command_line, cur_dir, process_startup,
diff --git a/chrome/browser/ui/startup/startup_browser_creator.h b/chrome/browser/ui/startup/startup_browser_creator.h
index 351d09e..bf3568b7 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.h
+++ b/chrome/browser/ui/startup/startup_browser_creator.h
@@ -10,7 +10,6 @@
 
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
-#include "base/macros.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/startup/startup_types.h"
@@ -31,6 +30,8 @@
   typedef std::vector<Profile*> Profiles;
 
   StartupBrowserCreator();
+  StartupBrowserCreator(const StartupBrowserCreator&) = delete;
+  StartupBrowserCreator& operator=(const StartupBrowserCreator&) = delete;
   ~StartupBrowserCreator();
 
   // Adds a url to be opened during first run. This overrides the standard
@@ -113,6 +114,10 @@
                            ReadingWasRestartedAfterRestart);
   FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest, UpdateWithTwoProfiles);
   FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest, LastUsedProfileActivated);
+  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest,
+                           ValidNotificationLaunchId);
+  FRIEND_TEST_ALL_PREFIXES(StartupBrowserCreatorTest,
+                           InvalidNotificationLaunchId);
 
   bool ProcessCmdLineImpl(const base::CommandLine& command_line,
                           const base::FilePath& cur_dir,
@@ -180,8 +185,6 @@
   static bool was_restarted_read_;
 
   static bool in_synchronous_profile_launch_;
-
-  DISALLOW_COPY_AND_ASSIGN(StartupBrowserCreator);
 };
 
 // Returns true if |profile| has exited uncleanly and has not been launched
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index 9b3ef23..7987cd3 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -11,7 +11,6 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/json/json_writer.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "base/strings/utf_string_conversions.h"
@@ -546,12 +545,9 @@
   command_line.AppendSwitchNative(
       switches::kNotificationLaunchId,
       L"1|1|0|Default|0|https://example.com/|notification_id");
-  chrome::startup::IsFirstRun first_run =
-      first_run::IsChromeFirstRun() ? chrome::startup::IS_FIRST_RUN
-                                    : chrome::startup::IS_NOT_FIRST_RUN;
-  StartupBrowserCreatorImpl launch(base::FilePath(), command_line, first_run);
-  ASSERT_TRUE(
-      launch.Launch(browser()->profile(), std::vector<GURL>(), false, nullptr));
+
+  ASSERT_TRUE(StartupBrowserCreator().ProcessCmdLineImpl(
+      command_line, base::FilePath(), false, browser()->profile(), {}));
 
   // The launch delegates to the notification system and doesn't open any new
   // browser window.
@@ -562,12 +558,9 @@
   // Simulate a launch with invalid launch id, which will fail.
   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
   command_line.AppendSwitchNative(switches::kNotificationLaunchId, L"");
-  chrome::startup::IsFirstRun first_run =
-      first_run::IsChromeFirstRun() ? chrome::startup::IS_FIRST_RUN
-                                    : chrome::startup::IS_NOT_FIRST_RUN;
-  StartupBrowserCreatorImpl launch(base::FilePath(), command_line, first_run);
-  ASSERT_FALSE(
-      launch.Launch(browser()->profile(), std::vector<GURL>(), false, nullptr));
+  StartupBrowserCreator browser_creator;
+  ASSERT_FALSE(StartupBrowserCreator().ProcessCmdLineImpl(
+      command_line, base::FilePath(), false, browser()->profile(), {}));
 
   // No new browser window is open.
   ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile()));
@@ -1197,6 +1190,10 @@
   StartupBrowserCreatorExtensionsCheckupExperimentTest() {
     set_open_about_blank_on_browser_launch(false);
   }
+  StartupBrowserCreatorExtensionsCheckupExperimentTest(
+      const StartupBrowserCreatorExtensionsCheckupExperimentTest&) = delete;
+  StartupBrowserCreatorExtensionsCheckupExperimentTest& operator=(
+      const StartupBrowserCreatorExtensionsCheckupExperimentTest&) = delete;
 
   void SetUp() override {
     // Enable the extensions checkup experiment.
@@ -1225,8 +1222,6 @@
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
-  DISALLOW_COPY_AND_ASSIGN(
-      StartupBrowserCreatorExtensionsCheckupExperimentTest);
 };
 
 // Test that when the extensions checkup experiment is enabled for the startup
@@ -1296,6 +1291,10 @@
   StartupBrowserCreatorFirstRunTest() {
     scoped_feature_list_.InitWithFeatures({welcome::kForceEnabled}, {});
   }
+  StartupBrowserCreatorFirstRunTest(const StartupBrowserCreatorFirstRunTest&) =
+      delete;
+  StartupBrowserCreatorFirstRunTest& operator=(
+      const StartupBrowserCreatorFirstRunTest&) = delete;
 
  protected:
   void SetUpCommandLine(base::CommandLine* command_line) override;
@@ -1306,8 +1305,6 @@
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(StartupBrowserCreatorFirstRunTest);
 };
 
 void StartupBrowserCreatorFirstRunTest::SetUpCommandLine(
@@ -1873,6 +1870,10 @@
   StartupBrowserCreatorPickerTest() {
     scoped_feature_list_.InitAndEnableFeature(features::kNewProfilePicker);
   }
+  StartupBrowserCreatorPickerTest(const StartupBrowserCreatorPickerTest&) =
+      delete;
+  StartupBrowserCreatorPickerTest& operator=(
+      const StartupBrowserCreatorPickerTest&) = delete;
   ~StartupBrowserCreatorPickerTest() override = default;
 
  protected:
@@ -1897,8 +1898,6 @@
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(StartupBrowserCreatorPickerTest);
 };
 
 // Flaky: https://crbug.com/1126886
diff --git a/chrome/browser/ui/startup/startup_browser_creator_corrupt_profiles_browsertest_win.cc b/chrome/browser/ui/startup/startup_browser_creator_corrupt_profiles_browsertest_win.cc
index accf36e..cd424a1 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_corrupt_profiles_browsertest_win.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_corrupt_profiles_browsertest_win.cc
@@ -110,8 +110,11 @@
 
 class StartupBrowserCreatorCorruptProfileTest : public InProcessBrowserTest {
  public:
-  StartupBrowserCreatorCorruptProfileTest()
-      : test_body_has_run_(false), expect_test_body_to_run_(true) {}
+  StartupBrowserCreatorCorruptProfileTest() = default;
+  StartupBrowserCreatorCorruptProfileTest(
+      const StartupBrowserCreatorCorruptProfileTest&) = delete;
+  StartupBrowserCreatorCorruptProfileTest& operator=(
+      const StartupBrowserCreatorCorruptProfileTest&) = delete;
 
   void SetExpectTestBodyToRun(bool expected_result) {
     expect_test_body_to_run_ = expected_result;
@@ -207,9 +210,8 @@
   }
 
  private:
-  bool test_body_has_run_;
-  bool expect_test_body_to_run_;
-  DISALLOW_COPY_AND_ASSIGN(StartupBrowserCreatorCorruptProfileTest);
+  bool test_body_has_run_ = false;
+  bool expect_test_body_to_run_ = true;
 };
 
 // Most of the tests below have three sections:
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index 87cd846..b8ad866 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -72,14 +72,9 @@
 #include "chrome/browser/ui/startup/mac_system_infobar_delegate.h"
 #endif
 
-#if defined(OS_WIN)
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
 #include "chrome/browser/win/conflicts/incompatible_applications_updater.h"
-#endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
-#include "chrome/browser/notifications/notification_platform_bridge_win.h"
-#include "chrome/browser/ui/startup/credential_provider_signin_dialog_win.h"
-#include "chrome/credential_provider/common/gcp_strings.h"
-#endif  // defined(OS_WIN)
+#endif
 
 #if BUILDFLAG(ENABLE_PLUGINS)
 #include "chrome/browser/plugins/flash_deprecation_infobar_delegate.h"
@@ -190,13 +185,9 @@
     chrome::startup::IsFirstRun is_first_run)
     : cur_dir_(cur_dir),
       command_line_(command_line),
-      profile_(nullptr),
       browser_creator_(browser_creator),
       is_first_run_(is_first_run == chrome::startup::IS_FIRST_RUN) {}
 
-StartupBrowserCreatorImpl::~StartupBrowserCreatorImpl() {
-}
-
 bool StartupBrowserCreatorImpl::Launch(
     Profile* profile,
     const std::vector<GURL>& urls_to_open,
@@ -205,40 +196,6 @@
   DCHECK(profile);
   profile_ = profile;
 
-#if defined(OS_WIN)
-  // If the command line has the kNotificationLaunchId switch, then this
-  // Launch() call is from notification_helper.exe to process toast activation.
-  // Delegate to the notification system; do not open a browser window here.
-  if (command_line_.HasSwitch(switches::kNotificationLaunchId)) {
-    if (NotificationPlatformBridgeWin::HandleActivation(command_line_)) {
-      if (launch_mode_recorder) {
-        launch_mode_recorder->SetLaunchMode(
-            LaunchMode::kWinPlatformNotification);
-      }
-      return true;
-    }
-    return false;
-  }
-  // If being started for credential provider logon purpose, only show the
-  // signin page.
-  if (command_line_.HasSwitch(credential_provider::kGcpwSigninSwitch)) {
-    DCHECK(profile_->IsIncognitoProfile());
-    // NOTE: All launch urls are ignored when running with --gcpw-signin since
-    // this mode only loads Google's sign in page.
-
-    // If GCPW signin dialog fails, returning false here will allow Chrome to
-    // exit gracefully during the launch.
-    if (!StartGCPWSignin(command_line_, profile_))
-      return false;
-
-    if (launch_mode_recorder) {
-      launch_mode_recorder->SetLaunchMode(
-          LaunchMode::kCredentialProviderSignIn);
-    }
-    return true;
-  }
-#endif  // defined(OS_WIN)
-
   if (command_line_.HasSwitch(switches::kAppId)) {
     std::string app_id = command_line_.GetSwitchValueASCII(switches::kAppId);
     // If |app_id| is a disabled or terminated platform app we handle it
@@ -377,7 +334,7 @@
 }
 
 bool StartupBrowserCreatorImpl::IsAppLaunch(std::string* app_url,
-                                            std::string* app_id) {
+                                            std::string* app_id) const {
   if (command_line_.HasSwitch(switches::kApp)) {
     if (app_url)
       *app_url = command_line_.GetSwitchValueASCII(switches::kApp);
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.h b/chrome/browser/ui/startup/startup_browser_creator_impl.h
index 17241bd..b8d1dc3 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.h
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.h
@@ -11,7 +11,6 @@
 
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
-#include "base/macros.h"
 #include "chrome/browser/sessions/session_restore.h"
 #include "chrome/browser/ui/startup/startup_tab.h"
 #include "chrome/browser/ui/startup/startup_types.h"
@@ -49,7 +48,10 @@
                             const base::CommandLine& command_line,
                             StartupBrowserCreator* browser_creator,
                             chrome::startup::IsFirstRun is_first_run);
-  ~StartupBrowserCreatorImpl();
+  StartupBrowserCreatorImpl(const StartupBrowserCreatorImpl&) = delete;
+  StartupBrowserCreatorImpl& operator=(const StartupBrowserCreatorImpl&) =
+      delete;
+  ~StartupBrowserCreatorImpl() = default;
 
   // Creates the necessary windows for startup. Returns true on success,
   // false on failure. process_startup is true if Chrome is just
@@ -128,7 +130,7 @@
   // If the process was launched with the web application command line flags,
   // e.g. --app=http://www.google.com/ or --app_id=... return true.
   // In this case |app_url| or |app_id| are populated if they're non-null.
-  bool IsAppLaunch(std::string* app_url, std::string* app_id);
+  bool IsAppLaunch(std::string* app_url, std::string* app_id) const;
 
   // Opens an application window or tab if the process was launched with the web
   // application command line switches. Returns true if launch succeeded (or is
@@ -196,10 +198,9 @@
 
   const base::FilePath cur_dir_;
   const base::CommandLine& command_line_;
-  Profile* profile_;
+  Profile* profile_ = nullptr;
   StartupBrowserCreator* browser_creator_;
   bool is_first_run_;
-  DISALLOW_COPY_AND_ASSIGN(StartupBrowserCreatorImpl);
 };
 
 #endif  // CHROME_BROWSER_UI_STARTUP_STARTUP_BROWSER_CREATOR_IMPL_H_
diff --git a/chrome/browser/ui/startup/startup_browser_creator_interactive_uitest.cc b/chrome/browser/ui/startup/startup_browser_creator_interactive_uitest.cc
index d09ec367..9ca878f 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_interactive_uitest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_interactive_uitest.cc
@@ -84,7 +84,7 @@
   while (!browser_creator.ActivatedProfile())
     base::RunLoop().RunUntilIdle();
 
-  Browser* new_browser = NULL;
+  Browser* new_browser = nullptr;
 
   // The last used profile (the profile_2 in this case) must be active.
   ASSERT_EQ(1u, chrome::GetBrowserCount(profile_2));
@@ -115,6 +115,10 @@
  public:
   explicit StartupPagePrefSetterMainExtraParts(const std::vector<GURL>& urls)
       : urls_(urls) {}
+  StartupPagePrefSetterMainExtraParts(
+      const StartupPagePrefSetterMainExtraParts&) = delete;
+  StartupPagePrefSetterMainExtraParts& operator=(
+      const StartupPagePrefSetterMainExtraParts&) = delete;
 
   // ChromeBrowserMainExtraParts:
   void PreBrowserStart() override {
@@ -128,7 +132,6 @@
 
  private:
   std::vector<GURL> urls_;
-  DISALLOW_COPY_AND_ASSIGN(StartupPagePrefSetterMainExtraParts);
 };
 
 class StartupPageTest : public InProcessBrowserTest {
@@ -137,6 +140,8 @@
     // Don't open about:blank since we want to test startup urls.
     set_open_about_blank_on_browser_launch(false);
   }
+  StartupPageTest(const StartupPageTest&) = delete;
+  StartupPageTest& operator=(const StartupPageTest&) = delete;
   ~StartupPageTest() override = default;
 
   // InProcessBrowserTest:
@@ -151,9 +156,6 @@
     chrome_browser_main_parts->AddParts(
         std::make_unique<StartupPagePrefSetterMainExtraParts>(urls));
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(StartupPageTest);
 };
 
 IN_PROC_BROWSER_TEST_F(StartupPageTest, StartupPageFocus) {
diff --git a/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc b/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
index 0b126bd..69e3458 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/callback_list.h"
 #include "base/command_line.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/win/windows_version.h"
@@ -58,6 +57,9 @@
 class MockTriggeredProfileResetter : public TriggeredProfileResetter {
  public:
   MockTriggeredProfileResetter() : TriggeredProfileResetter(nullptr) {}
+  MockTriggeredProfileResetter(const MockTriggeredProfileResetter&) = delete;
+  MockTriggeredProfileResetter& operator=(const MockTriggeredProfileResetter&) =
+      delete;
 
   void Activate() override {}
   bool HasResetTrigger() override { return has_reset_trigger_; }
@@ -67,7 +69,6 @@
 
  private:
   static bool has_reset_trigger_;
-  DISALLOW_COPY_AND_ASSIGN(MockTriggeredProfileResetter);
 };
 
 bool MockTriggeredProfileResetter::has_reset_trigger_ = false;
@@ -86,7 +87,11 @@
 
 class StartupBrowserCreatorTriggeredResetTest : public InProcessBrowserTest {
  public:
-  StartupBrowserCreatorTriggeredResetTest() {}
+  StartupBrowserCreatorTriggeredResetTest() = default;
+  StartupBrowserCreatorTriggeredResetTest(
+      const StartupBrowserCreatorTriggeredResetTest&) = delete;
+  StartupBrowserCreatorTriggeredResetTest& operator=(
+      const StartupBrowserCreatorTriggeredResetTest&) = delete;
 
  protected:
   void SetUpInProcessBrowserTestFixture() override {
@@ -107,8 +112,6 @@
   std::unique_ptr<
       BrowserContextDependencyManager::CreateServicesCallbackList::Subscription>
       create_services_subscription_;
-
-  DISALLOW_COPY_AND_ASSIGN(StartupBrowserCreatorTriggeredResetTest);
 };
 
 IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTriggeredResetTest,
diff --git a/chrome/browser/ui/startup/startup_browser_policy_unittest.cc b/chrome/browser/ui/startup/startup_browser_policy_unittest.cc
index 7540cfd9..380ef16 100644
--- a/chrome/browser/ui/startup/startup_browser_policy_unittest.cc
+++ b/chrome/browser/ui/startup/startup_browser_policy_unittest.cc
@@ -50,6 +50,11 @@
 };
 
 class StartupBrowserPolicyUnitTest : public testing::Test {
+ public:
+  StartupBrowserPolicyUnitTest(const StartupBrowserPolicyUnitTest&) = delete;
+  StartupBrowserPolicyUnitTest& operator=(const StartupBrowserPolicyUnitTest&) =
+      delete;
+
  protected:
   StartupBrowserPolicyUnitTest() = default;
   ~StartupBrowserPolicyUnitTest() override = default;
@@ -109,9 +114,6 @@
     SetPolicy(*policy_map.get(), policy, args...);
     return policy_map;
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(StartupBrowserPolicyUnitTest);
 };
 
 TEST_F(StartupBrowserPolicyUnitTest, BookmarkBarEnabled) {
diff --git a/chrome/browser/ui/startup/startup_tab_provider.h b/chrome/browser/ui/startup/startup_tab_provider.h
index a088086..03870d4 100644
--- a/chrome/browser/ui/startup/startup_tab_provider.h
+++ b/chrome/browser/ui/startup/startup_tab_provider.h
@@ -78,6 +78,8 @@
   };
 
   StartupTabProviderImpl() = default;
+  StartupTabProviderImpl(const StartupTabProviderImpl&) = delete;
+  StartupTabProviderImpl& operator=(const StartupTabProviderImpl&) = delete;
 
   // The static helper methods below implement the policies relevant to the
   // respective Get*Tabs methods, but do not gather or interact with any
@@ -170,9 +172,6 @@
       bool has_incompatible_applications) const override;
   StartupTabs GetExtensionCheckupTabs(
       bool serve_extensions_page) const override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(StartupTabProviderImpl);
 };
 
 #endif  // CHROME_BROWSER_UI_STARTUP_STARTUP_TAB_PROVIDER_H_
diff --git a/chrome/browser/ui/views/apps/app_dialog/app_uninstall_dialog_view.cc b/chrome/browser/ui/views/apps/app_dialog/app_uninstall_dialog_view.cc
index 6a62dbf0..d47e36e 100644
--- a/chrome/browser/ui/views/apps/app_dialog/app_uninstall_dialog_view.cc
+++ b/chrome/browser/ui/views/apps/app_dialog/app_uninstall_dialog_view.cc
@@ -147,7 +147,7 @@
   switch (app_type) {
     case apps::mojom::AppType::kUnknown:
     case apps::mojom::AppType::kBuiltIn:
-    case apps::mojom::AppType::kMacNative:
+    case apps::mojom::AppType::kMacOs:
     case apps::mojom::AppType::kLacros:
     case apps::mojom::AppType::kRemote:
     case apps::mojom::AppType::kBorealis:
diff --git a/chrome/browser/ui/views/borealis/borealis_installer_view.cc b/chrome/browser/ui/views/borealis/borealis_installer_view.cc
index b7c364b..5d012d0 100644
--- a/chrome/browser/ui/views/borealis/borealis_installer_view.cc
+++ b/chrome/browser/ui/views/borealis/borealis_installer_view.cc
@@ -166,6 +166,9 @@
 
 BorealisInstallerView::~BorealisInstallerView() {
   borealis_installer_->RemoveObserver(this);
+  if (state_ == State::kConfirmInstall || state_ == State::kInstalling) {
+    borealis_installer_->Cancel();
+  }
   g_borealis_installer_view = nullptr;
 }
 
@@ -203,10 +206,6 @@
 }
 
 bool BorealisInstallerView::Cancel() {
-  if (state_ == State::kConfirmInstall || state_ == State::kInstalling) {
-    borealis_installer_->Cancel();
-  }
-
   return true;
 }
 
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.cc b/chrome/browser/ui/views/profiles/profile_menu_view.cc
index 37297e4..7d5b8a3 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view.cc
@@ -167,7 +167,6 @@
 
 ProfileMenuView::ProfileMenuView(views::Button* anchor_button, Browser* browser)
     : ProfileMenuViewBase(anchor_button, browser) {
-  GetViewAccessibility().OverrideName(GetAccessibleWindowTitle());
   chrome::RecordDialogCreation(chrome::DialogIdentifier::PROFILE_CHOOSER);
   set_close_on_deactivate(close_on_deactivate_for_testing_);
 }
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
index e7598b1..e94260d 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -562,6 +562,13 @@
 
   auto avatar_image_view = std::make_unique<AvatarImageView>(image_model, this);
 
+  // Use the profile identity info to label the entire menu, for accessibility
+  // users to get the user account as context information when they open it.
+  const base::string16& accessible_menu_name =
+      title.empty() ? (subtitle.empty() ? GetAccessibleWindowTitle() : subtitle)
+                    : title;
+  GetViewAccessibility().OverrideName(accessible_menu_name);
+
   if (!new_design) {
     if (!profile_name.empty()) {
       DCHECK(edit_button_params.has_value());
@@ -698,6 +705,10 @@
   label->SetMultiLine(true);
   label->SetHandlesTooltips(false);
 
+  // Required for accessibility tools to read the description together with the
+  // button text.
+  sync_info_container_->GetViewAccessibility().OverrideName(description);
+
   // Add the prominent button at the bottom.
   auto* button =
       sync_info_container_->AddChildView(std::make_unique<views::MdTextButton>(
@@ -763,6 +774,8 @@
 
 void ProfileMenuViewBase::SetProfileManagementHeading(
     const base::string16& heading) {
+  profile_mgmt_heading_ = heading;
+
   // Add separator before heading.
   profile_mgmt_separator_container_->RemoveAllChildViews(
       /*delete_children=*/true);
@@ -799,6 +812,10 @@
     selectable_profiles_container_->SetLayoutManager(
         std::make_unique<views::BoxLayout>(
             views::BoxLayout::Orientation::kVertical));
+    // Give the container an accessible name so accessibility tools can provide
+    // context for the buttons inside it.
+    selectable_profiles_container_->GetViewAccessibility().OverrideName(
+        profile_mgmt_heading_);
   }
 
   DCHECK(!image_model.IsEmpty());
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.h b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
index 240d566..2c190b3 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.h
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
@@ -219,6 +219,9 @@
   SyncInfoContainerBackgroundState sync_background_state_ =
       SyncInfoContainerBackgroundState::kNoError;
 
+  // Actual heading string would be set by children classes.
+  base::string16 profile_mgmt_heading_;
+
   DISALLOW_COPY_AND_ASSIGN(ProfileMenuViewBase);
 };
 
diff --git a/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.cc b/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.cc
index c684232..cd660b13 100644
--- a/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.cc
+++ b/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.cc
@@ -19,6 +19,7 @@
 #include "extensions/browser/app_window/app_window.h"
 #include "extensions/browser/app_window/app_window_registry.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/accessibility/ax_enums.mojom-forward.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/font_list.h"
@@ -327,6 +328,13 @@
   View::OnKeyEvent(event);
 }
 
+ax::mojom::Role SharesheetBubbleView::GetAccessibleWindowRole() {
+  // We override the role because the base class sets it to alert dialog.
+  // This would make screen readers repeatedly announce the whole of the
+  // |sharesheet_bubble_view| which is undesirable.
+  return ax::mojom::Role::kDialog;
+}
+
 std::unique_ptr<views::NonClientFrameView>
 SharesheetBubbleView::CreateNonClientFrameView(views::Widget* widget) {
   auto bubble_border =
@@ -339,6 +347,10 @@
   return frame;
 }
 
+gfx::Size SharesheetBubbleView::CalculatePreferredSize() const {
+  return gfx::Size(width_, height_);
+}
+
 void SharesheetBubbleView::OnWidgetDestroyed(views::Widget* widget) {
   // If there is no active_target_ value, the user cancelled without making a
   // selection and we will record this.
@@ -352,10 +364,6 @@
   }
 }
 
-gfx::Size SharesheetBubbleView::CalculatePreferredSize() const {
-  return gfx::Size(width_, height_);
-}
-
 void SharesheetBubbleView::CreateBubble() {
   set_close_on_deactivate(true);
   SetButtons(ui::DIALOG_BUTTON_NONE);
diff --git a/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.h b/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.h
index 9b389ea..b329aa2 100644
--- a/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.h
+++ b/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.h
@@ -46,14 +46,15 @@
   void CloseBubble();
 
  private:
-  // ui::EventHandler overrides:
+  // ui::EventHandler:
   void OnKeyEvent(ui::KeyEvent* event) override;
 
-  // views::WidgetDelegate override
+  // views::WidgetDelegate:
+  ax::mojom::Role GetAccessibleWindowRole() override;
   std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView(
       views::Widget* widget) override;
 
-  // views::BubbleDialogDelegateView overrides
+  // views::BubbleDialogDelegateView:
   gfx::Size CalculatePreferredSize() const override;
   void OnWidgetDestroyed(views::Widget* widget) override;
 
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 6f773fc..e330df1 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-master-1603560761-17d72f8640dc7847ade4cf9bfef5e8e7c2746b8c.profdata
+chrome-linux-master-1603691326-ded4cf98fc57f32e31937f939ee80f292f889c4d.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 337fcb6..332d043 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-master-1603540106-f9997f455c401b6699b57b30de616e21c0c02270.profdata
+chrome-win32-master-1603613972-73699eb7c90ca72304abe78e4e06ee3df85b698a.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index ac0d1a5..97a94aa 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1603551129-db90a4722cc0b0a38570ed85a830a87d0465f9e9.profdata
+chrome-win64-master-1603659384-78fe2392c0cc8d75dc2caf4c010bfa3581cbc33b.profdata
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl
index 1702270..1573ec0 100644
--- a/chrome/common/extensions/api/autotest_private.idl
+++ b/chrome/common/extensions/api/autotest_private.idl
@@ -35,7 +35,7 @@
     Crostini,
     Extension,
     Web,
-    MacNative,
+    MacOS,
     PluginVm,
     Lacros,
     Remote,
diff --git a/chrome/test/data/webui/js/cr/ui/BUILD.gn b/chrome/test/data/webui/js/cr/ui/BUILD.gn
index e6a76361..8136672 100644
--- a/chrome/test/data/webui/js/cr/ui/BUILD.gn
+++ b/chrome/test/data/webui/js/cr/ui/BUILD.gn
@@ -7,11 +7,18 @@
 
 js_modulizer("modulize") {
   input_files = [
-    "grid_test.js",
     "array_data_model_test.js",
     "command_test.js",
     "context_menu_handler_test.js",
+    "grid_test.js",
+    "list_selection_model_test.js",
+    "list_selection_model_test_util.js",
+    "list_single_selection_model_test.js",
     "list_test.js",
+    "menu_button_test.js",
+    "menu_test.js",
+    "position_util_test.js",
+    "splitter_test.js",
   ]
 
   namespace_rewrites = cr_namespace_rewrites
diff --git a/chrome/test/data/webui/js/cr/ui/list_selection_model_test.js b/chrome/test/data/webui/js/cr/ui/list_selection_model_test.js
index a765e36f..6de9562 100644
--- a/chrome/test/data/webui/js/cr/ui/list_selection_model_test.js
+++ b/chrome/test/data/webui/js/cr/ui/list_selection_model_test.js
@@ -2,13 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import {ListSelectionModel} from 'chrome://resources/js/cr/ui/list_selection_model.m.js';
+// #import {adjust, range} from './list_selection_model_test_util.m.js';
+// clang-format on
+
 function createSelectionModel(len, opt_dependentLeadItem) {
   var sm = new cr.ui.ListSelectionModel(len);
   sm.independentLeadItem_ = !opt_dependentLeadItem;
   return sm;
 }
 
-function testAdjust1() {
+/* #export */ function testAdjust1() {
   var sm = createSelectionModel(200);
 
   sm.leadIndex = sm.anchorIndex = sm.selectedIndex = 100;
@@ -19,7 +24,7 @@
   assertEquals(90, sm.selectedIndex);
 }
 
-function testAdjust2() {
+/* #export */ function testAdjust2() {
   var sm = createSelectionModel(200);
 
   sm.leadIndex = sm.anchorIndex = sm.selectedIndex = 50;
@@ -30,7 +35,7 @@
   assertEquals(50, sm.selectedIndex);
 }
 
-function testAdjust3() {
+/* #export */ function testAdjust3() {
   var sm = createSelectionModel(200);
 
   sm.leadIndex = sm.anchorIndex = sm.selectedIndex = 100;
@@ -41,7 +46,7 @@
   assertEquals(110, sm.selectedIndex);
 }
 
-function testAdjust4() {
+/* #export */ function testAdjust4() {
   var sm = createSelectionModel(200);
 
   sm.leadIndex = sm.anchorIndex = 100;
@@ -54,7 +59,7 @@
   assertArrayEquals(range(95, 105), sm.selectedIndexes);
 }
 
-function testAdjust5() {
+/* #export */ function testAdjust5() {
   var sm = createSelectionModel(100);
 
   sm.leadIndex = sm.anchorIndex = sm.selectedIndex = 99;
@@ -66,7 +71,7 @@
   assertArrayEquals([98], sm.selectedIndexes);
 }
 
-function testAdjust6() {
+/* #export */ function testAdjust6() {
   var sm = createSelectionModel(200);
 
   sm.leadIndex = sm.anchorIndex = 105;
@@ -80,7 +85,7 @@
   assertArrayEquals(range(100, 105), sm.selectedIndexes);
 }
 
-function testAdjust7() {
+/* #export */ function testAdjust7() {
   var sm = createSelectionModel(1);
 
   sm.leadIndex = sm.anchorIndex = sm.selectedIndex = 0;
@@ -92,7 +97,7 @@
   assertArrayEquals([10], sm.selectedIndexes);
 }
 
-function testAdjust8() {
+/* #export */ function testAdjust8() {
   var sm = createSelectionModel(100);
 
   sm.leadIndex = sm.anchorIndex = 50;
@@ -105,7 +110,7 @@
   assertArrayEquals(range(0, 19), sm.selectedIndexes);
 }
 
-function testAdjust9() {
+/* #export */ function testAdjust9() {
   var sm = createSelectionModel(10);
 
   sm.leadIndex = sm.anchorIndex = 5;
@@ -119,7 +124,7 @@
   assertArrayEquals([], sm.selectedIndexes);
 }
 
-function testAdjust10() {
+/* #export */ function testAdjust10() {
   var sm = createSelectionModel(10);
 
   sm.leadIndex = sm.anchorIndex = 5;
@@ -132,7 +137,7 @@
   assertArrayEquals([5], sm.selectedIndexes);
 }
 
-function testAdjust11() {
+/* #export */ function testAdjust11() {
   var sm = createSelectionModel(20);
 
   sm.leadIndex = sm.anchorIndex = 10;
@@ -145,7 +150,7 @@
   assertArrayEquals(range(0, 4), sm.selectedIndexes);
 }
 
-function testAdjust12() {
+/* #export */ function testAdjust12() {
   var sm = createSelectionModel(20, true);
 
   sm.selectAll();
@@ -158,7 +163,7 @@
   assertArrayEquals(range(0, 4), sm.selectedIndexes);
 }
 
-function testAdjust13() {
+/* #export */ function testAdjust13() {
   var sm = createSelectionModel(20, true);
 
   sm.selectAll();
@@ -171,7 +176,7 @@
   assertArrayEquals(range(0, 14), sm.selectedIndexes);
 }
 
-function testAdjust14() {
+/* #export */ function testAdjust14() {
   var sm = createSelectionModel(5, true);
 
   sm.selectedIndexes = [2, 3];
@@ -184,7 +189,7 @@
   assertArrayEquals(range(2, 2), sm.selectedIndexes);
 }
 
-function testAdjust15() {
+/* #export */ function testAdjust15() {
   var sm = createSelectionModel(7, true);
 
   sm.selectedIndexes = [1, 3, 5];
@@ -199,7 +204,7 @@
   assertArrayEquals(range(3, 3), sm.selectedIndexes);
 }
 
-function testAdjust16() {
+/* #export */ function testAdjust16() {
   var sm = createSelectionModel(7, true);
 
   sm.selectedIndexes = [1, 3, 5];
@@ -214,7 +219,7 @@
   assertArrayEquals(range(3, 3), sm.selectedIndexes);
 }
 
-function testAdjust17() {
+/* #export */ function testAdjust17() {
   var sm = createSelectionModel(7, true);
 
   sm.selectedIndexes = [1, 3, 5];
@@ -229,7 +234,7 @@
   assertArrayEquals(range(3, 3), sm.selectedIndexes);
 }
 
-function testLeadAndAnchor1() {
+/* #export */ function testLeadAndAnchor1() {
   var sm = createSelectionModel(20, true);
 
   sm.selectAll();
@@ -239,7 +244,7 @@
   assertEquals(10, sm.anchorIndex, 'anchor');
 }
 
-function testLeadAndAnchor2() {
+/* #export */ function testLeadAndAnchor2() {
   var sm = createSelectionModel(20, true);
 
   sm.leadIndex = sm.anchorIndex = 10;
@@ -249,7 +254,7 @@
   assertEquals(0, sm.anchorIndex, 'anchor');
 }
 
-function testSelectAll() {
+/* #export */ function testSelectAll() {
   var sm = createSelectionModel(10);
 
   var changes = null;
@@ -265,7 +270,7 @@
   }));
 }
 
-function testSelectAllOnEmptyList() {
+/* #export */ function testSelectAllOnEmptyList() {
   var sm = createSelectionModel(0);
 
   var changes = null;
@@ -278,3 +283,27 @@
   assertArrayEquals([], sm.selectedIndexes);
   assertEquals(null, changes);
 }
+
+Object.assign(window, {
+  testAdjust1,
+  testAdjust2,
+  testAdjust3,
+  testAdjust4,
+  testAdjust5,
+  testAdjust6,
+  testAdjust7,
+  testAdjust8,
+  testAdjust9,
+  testAdjust10,
+  testAdjust11,
+  testAdjust12,
+  testAdjust13,
+  testAdjust14,
+  testAdjust15,
+  testAdjust16,
+  testAdjust17,
+  testLeadAndAnchor1,
+  testLeadAndAnchor2,
+  testSelectAll,
+  testSelectAllOnEmptyList,
+});
diff --git a/chrome/test/data/webui/js/cr/ui/list_selection_model_test_util.js b/chrome/test/data/webui/js/cr/ui/list_selection_model_test_util.js
index a604dc4c..1a18080 100644
--- a/chrome/test/data/webui/js/cr/ui/list_selection_model_test_util.js
+++ b/chrome/test/data/webui/js/cr/ui/list_selection_model_test_util.js
@@ -8,7 +8,7 @@
  * @param {number} end The last number in the range inclusive.
  * @return {!Array<number>}
  */
-function range(start, end) {
+/* #export */ function range(start, end) {
   var a = [];
   for (var i = start; i <= end; i++) {
     a.push(i);
@@ -23,7 +23,7 @@
  * @param {number} removed Number of entries to remove from the list.
  * @param {number} added Number of entries to add to the list.
  */
-function adjust(model, index, removed, added) {
+/* #export */ function adjust(model, index, removed, added) {
   var permutation = [];
   for (var i = 0; i < index; i++) {
     permutation.push(i);
diff --git a/chrome/test/data/webui/js/cr/ui/list_single_selection_model_test.js b/chrome/test/data/webui/js/cr/ui/list_single_selection_model_test.js
index 3e3c5335..40f5d96a 100644
--- a/chrome/test/data/webui/js/cr/ui/list_single_selection_model_test.js
+++ b/chrome/test/data/webui/js/cr/ui/list_single_selection_model_test.js
@@ -2,13 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import {ListSingleSelectionModel} from 'chrome://resources/js/cr/ui/list_single_selection_model.m.js';
+// #import {adjust} from './list_selection_model_test_util.m.js';
+// clang-format on
+
 function createSelectionModel(len, opt_dependentLeadItem) {
   var sm = new cr.ui.ListSingleSelectionModel(len);
   sm.independentLeadItem_ = !opt_dependentLeadItem;
   return sm;
 }
 
-function testAdjust1() {
+/* #export */ function testAdjust1() {
   var sm = createSelectionModel(200);
 
   sm.leadIndex = sm.anchorIndex = sm.selectedIndex = 100;
@@ -19,7 +24,7 @@
   assertEquals(90, sm.selectedIndex);
 }
 
-function testAdjust2() {
+/* #export */ function testAdjust2() {
   var sm = createSelectionModel(200);
 
   sm.leadIndex = sm.anchorIndex = sm.selectedIndex = 50;
@@ -30,7 +35,7 @@
   assertEquals(50, sm.selectedIndex);
 }
 
-function testAdjust3() {
+/* #export */ function testAdjust3() {
   var sm = createSelectionModel(200);
 
   sm.leadIndex = sm.anchorIndex = sm.selectedIndex = 100;
@@ -41,7 +46,7 @@
   assertEquals(110, sm.selectedIndex);
 }
 
-function testAdjust4() {
+/* #export */ function testAdjust4() {
   var sm = createSelectionModel(100);
 
   sm.leadIndex = sm.anchorIndex = sm.selectedIndex = 99;
@@ -53,7 +58,7 @@
   assertArrayEquals([], sm.selectedIndexes);
 }
 
-function testAdjust5() {
+/* #export */ function testAdjust5() {
   var sm = createSelectionModel(1);
 
   sm.leadIndex = sm.anchorIndex = sm.selectedIndex = 0;
@@ -65,7 +70,7 @@
   assertArrayEquals([10], sm.selectedIndexes);
 }
 
-function testSelectedIndex1() {
+/* #export */ function testSelectedIndex1() {
   var sm = createSelectionModel(100, true);
 
   sm.selectedIndex = 99;
@@ -75,7 +80,7 @@
   assertArrayEquals([99], sm.selectedIndexes);
 }
 
-function testLeadIndex1() {
+/* #export */ function testLeadIndex1() {
   var sm = createSelectionModel(100);
 
   sm.leadIndex = 99;
@@ -85,7 +90,7 @@
   assertArrayEquals([], sm.selectedIndexes);
 }
 
-function testLeadIndex2() {
+/* #export */ function testLeadIndex2() {
   var sm = createSelectionModel(100, true);
 
   sm.leadIndex = 99;
@@ -94,3 +99,14 @@
   assertEquals(-1, sm.anchorIndex, 'anchor');
   assertArrayEquals([], sm.selectedIndexes);
 }
+
+Object.assign(window, {
+  testAdjust1,
+  testAdjust2,
+  testAdjust3,
+  testAdjust4,
+  testAdjust5,
+  testSelectedIndex1,
+  testLeadIndex1,
+  testLeadIndex2,
+});
diff --git a/chrome/test/data/webui/js/cr/ui/menu_button_test.js b/chrome/test/data/webui/js/cr/ui/menu_button_test.js
index 57f938e4..ce5ae021 100644
--- a/chrome/test/data/webui/js/cr/ui/menu_button_test.js
+++ b/chrome/test/data/webui/js/cr/ui/menu_button_test.js
@@ -2,7 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function testMenuShowAndHideEvents() {
+// #import {Menu} from 'chrome://resources/js/cr/ui/menu.m.js';
+// #import {MenuButton} from 'chrome://resources/js/cr/ui/menu_button.m.js';
+// #import {decorate} from 'chrome://resources/js/cr/ui.m.js';
+
+/* #export */ function testMenuShowAndHideEvents() {
   var menu = document.createElement('div');
   cr.ui.decorate(menu, cr.ui.Menu);
   document.body.appendChild(menu);
@@ -51,7 +55,7 @@
   assertFalse(menuButton.classList.contains('using-mouse'));
 }
 
-function testFocusMoves() {
+/* #export */ function testFocusMoves() {
   var menu = document.createElement('div');
   var otherButton = document.createElement('button');
   cr.ui.decorate(menu, cr.ui.Menu);
@@ -101,3 +105,8 @@
   // Focus should be still on the menu button.
   assertEquals(menuButton, document.activeElement);
 }
+
+Object.assign(window, {
+  testMenuShowAndHideEvents,
+  testFocusMoves,
+});
diff --git a/chrome/test/data/webui/js/cr/ui/menu_test.js b/chrome/test/data/webui/js/cr/ui/menu_test.js
index 149fbac..b88d413e 100644
--- a/chrome/test/data/webui/js/cr/ui/menu_test.js
+++ b/chrome/test/data/webui/js/cr/ui/menu_test.js
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// #import {decorate} from 'chrome://resources/js/cr/ui.m.js';
+// #import {Command} from 'chrome://resources/js/cr/ui/command.m.js';
+// #import {Menu} from 'chrome://resources/js/cr/ui/menu.m.js';
+// #import {MenuItem} from 'chrome://resources/js/cr/ui/menu_item.m.js';
+
 /** @type {cr.ui.Menu} */
 var menu;
 
@@ -21,11 +26,11 @@
   return menu.dispatchEvent(mouseUpEvent);
 }
 
-function setUp() {
+/* #export */ function setUp() {
   menu = new cr.ui.Menu;
 }
 
-function testHandleMouseOver() {
+/* #export */ function testHandleMouseOver() {
   var called = false;
   menu.findMenuItem_ = function() {
     called = true;
@@ -39,7 +44,7 @@
   assertTrue(called);
 }
 
-function testHandleMouseUp() {
+/* #export */ function testHandleMouseUp() {
   var realNow = Date.now;
   Date.now = function() {
     return 10;
@@ -62,7 +67,7 @@
   Date.now = realNow;
 }
 
-function testShowViaKeyboardIgnoresMouseUps() {
+/* #export */ function testShowViaKeyboardIgnoresMouseUps() {
   menu.show();
   assertTrue(mouseUpAt(0, 0));
 }
@@ -71,7 +76,7 @@
  * Tests that if the command attributes are spacified, they are copied to the
  * corresponding menuitem.
  */
-function testCommandMenuItem() {
+/* #export */ function testCommandMenuItem() {
   // Test 1: The case that the command label is set and other attributes copied.
   var command = new cr.ui.Command();
   command.id = 'the-command';
@@ -135,7 +140,7 @@
  * non-separator item on both sides of it. Further, ensure that multiple
  * separators will not be displayed adjacent to each other.
  */
-function testSeparators() {
+/* #export */ function testSeparators() {
   const menuItems = [];
   menu.addSeparator();
   menuItems.push(menu.addMenuItem({label: 'a'}));
@@ -158,7 +163,7 @@
 /**
  * Tests that focusSelectedItem() ignores hidden and disabled items.
  */
-function testFocusSelectedItems() {
+/* #export */ function testFocusSelectedItems() {
   const menu = document.createElement('div');
   cr.ui.decorate(menu, cr.ui.Menu);
   const item1 = menu.addMenuItem({label: 'item1'});
@@ -210,7 +215,7 @@
 /**
  * Tests that cr.ui.MenuItem defaults to tabindex=-1.
  */
-function testMenuItemTabIndex() {
+/* #export */ function testMenuItemTabIndex() {
   // Defaults to -1.
   const item1 = menu.addMenuItem({label: 'item 1'});
   assertEquals('-1', item1.getAttribute('tabindex'));
@@ -227,3 +232,14 @@
   assertTrue(separator.isSeparator());
   assertFalse(separator.hasAttribute('tabindex'));
 }
+
+Object.assign(window, {
+  setUp,
+  testHandleMouseOver,
+  testHandleMouseUp,
+  testShowViaKeyboardIgnoresMouseUps,
+  testCommandMenuItem,
+  testSeparators,
+  testFocusSelectedItems,
+  testMenuItemTabIndex,
+});
diff --git a/chrome/test/data/webui/js/cr/ui/position_util_test.html b/chrome/test/data/webui/js/cr/ui/position_util_test.html
index 0dff7628..7860578 100644
--- a/chrome/test/data/webui/js/cr/ui/position_util_test.html
+++ b/chrome/test/data/webui/js/cr/ui/position_util_test.html
@@ -1,40 +1,10 @@
 <!DOCTYPE html>
 <html>
 <head>
-<style>
-
-html, body {
-  margin: 0;
-  width: 100%;
-  height: 100%;
-}
-
-#anchor {
-  position: absolute;
-  width: 10px;
-  height: 10px;
-  background: green;
-}
-
-#popup {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100px;
-  height: 100px;
-  background: red;
-}
-
-</style>
 </head>
 <body>
-
-<div id=anchor></div>
-<div id=popup></div>
-
 <script src="chrome://resources/js/cr.js"></script>
 <script src="chrome://resources/js/cr/ui/position_util.js"></script>
 <script src="position_util_test.js"></script>
-
 </body>
 </html>
diff --git a/chrome/test/data/webui/js/cr/ui/position_util_test.js b/chrome/test/data/webui/js/cr/ui/position_util_test.js
index fae85100f..7b92ab0 100644
--- a/chrome/test/data/webui/js/cr/ui/position_util_test.js
+++ b/chrome/test/data/webui/js/cr/ui/position_util_test.js
@@ -2,11 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-var anchor = document.getElementById('anchor');
-var popup = document.getElementById('popup');
-var anchorParent = anchor.offsetParent;
-var oldGetBoundingClientRect = anchorParent.getBoundingClientRect;
-var availRect;
+// clang-format off
+// #import {positionPopupAroundElement, positionPopupAtPoint, AnchorType} from 'chrome://resources/js/cr/ui/position_util.m.js';
+// clang-format on
+
+let anchor;
+let popup;
+let anchorParent;
+let oldGetBoundingClientRect;
+let availRect;
 
 function MockRect(w, h) {
   this.width = w;
@@ -19,7 +23,41 @@
   top: 0
 };
 
-function setUp() {
+/* #export */ function setUp() {
+  document.body.innerHTML = `
+    <style>
+      html, body {
+        margin: 0;
+        width: 100%;
+        height: 100%;
+      }
+
+      #anchor {
+        position: absolute;
+        width: 10px;
+        height: 10px;
+        background: green;
+      }
+
+      #popup {
+        position: absolute;
+        top: 0;
+        left: 0;
+        width: 100px;
+        height: 100px;
+        background: red;
+      }
+    </style>
+
+    <div id="anchor"></div>
+    <div id="popup"></div>
+    `;
+
+  anchor = document.getElementById('anchor');
+  popup = document.getElementById('popup');
+  anchorParent = anchor.offsetParent;
+  oldGetBoundingClientRect = anchorParent.getBoundingClientRect;
+
   anchor.style.top = '100px';
   anchor.style.left = '100px';
   availRect = new MockRect(200, 200);
@@ -28,12 +66,12 @@
   };
 }
 
-function tearDown() {
+/* #export */ function tearDown() {
   document.documentElement.dir = 'ltr';
   anchorParent.getBoundingClientRect = oldGetBoundingClientRect;
 }
 
-function testAbovePrimary() {
+/* #export */ function testAbovePrimary() {
   cr.ui.positionPopupAroundElement(anchor, popup, cr.ui.AnchorType.ABOVE);
 
   assertEquals('auto', popup.style.top);
@@ -45,7 +83,7 @@
   assertEquals('auto', popup.style.bottom);
 }
 
-function testBelowPrimary() {
+/* #export */ function testBelowPrimary() {
   // ensure enough below
   anchor.style.top = '90px';
 
@@ -62,7 +100,7 @@
   assertEquals('100px', popup.style.bottom);
 }
 
-function testBeforePrimary() {
+/* #export */ function testBeforePrimary() {
   cr.ui.positionPopupAroundElement(anchor, popup, cr.ui.AnchorType.BEFORE);
 
   assertEquals('auto', popup.style.left);
@@ -74,7 +112,7 @@
   assertEquals('auto', popup.style.right);
 }
 
-function testBeforePrimaryRtl() {
+/* #export */ function testBeforePrimaryRtl() {
   document.documentElement.dir = 'rtl';
 
   cr.ui.positionPopupAroundElement(anchor, popup, cr.ui.AnchorType.AFTER);
@@ -89,7 +127,7 @@
   assertEquals('auto', popup.style.right);
 }
 
-function testAfterPrimary() {
+/* #export */ function testAfterPrimary() {
   // ensure enough to the right
   anchor.style.left = '90px';
 
@@ -106,7 +144,7 @@
   assertEquals('100px', popup.style.right);
 }
 
-function testAfterPrimaryRtl() {
+/* #export */ function testAfterPrimaryRtl() {
   document.documentElement.dir = 'rtl';
 
   cr.ui.positionPopupAroundElement(anchor, popup, cr.ui.AnchorType.AFTER);
@@ -122,7 +160,7 @@
   assertEquals('auto', popup.style.right);
 }
 
-function testAboveSecondary() {
+/* #export */ function testAboveSecondary() {
   cr.ui.positionPopupAroundElement(anchor, popup, cr.ui.AnchorType.ABOVE);
 
   assertEquals('100px', popup.style.left);
@@ -136,7 +174,7 @@
   assertEquals('80px', popup.style.right);
 }
 
-function testAboveSecondaryRtl() {
+/* #export */ function testAboveSecondaryRtl() {
   document.documentElement.dir = 'rtl';
 
   cr.ui.positionPopupAroundElement(anchor, popup, cr.ui.AnchorType.ABOVE);
@@ -152,7 +190,7 @@
   assertEquals('auto', popup.style.right);
 }
 
-function testAboveSecondarySwappedAlign() {
+/* #export */ function testAboveSecondarySwappedAlign() {
   cr.ui.positionPopupAroundElement(anchor, popup, cr.ui.AnchorType.ABOVE, true);
 
   assertEquals('auto', popup.style.left);
@@ -166,7 +204,7 @@
   assertEquals('auto', popup.style.right);
 }
 
-function testBelowSecondary() {
+/* #export */ function testBelowSecondary() {
   cr.ui.positionPopupAroundElement(anchor, popup, cr.ui.AnchorType.BELOW);
 
   assertEquals('100px', popup.style.left);
@@ -180,7 +218,7 @@
   assertEquals('80px', popup.style.right);
 }
 
-function testBelowSecondaryRtl() {
+/* #export */ function testBelowSecondaryRtl() {
   document.documentElement.dir = 'rtl';
 
   cr.ui.positionPopupAroundElement(anchor, popup, cr.ui.AnchorType.BELOW);
@@ -196,7 +234,7 @@
   assertEquals('auto', popup.style.right);
 }
 
-function testBelowSecondarySwappedAlign() {
+/* #export */ function testBelowSecondarySwappedAlign() {
   cr.ui.positionPopupAroundElement(anchor, popup, cr.ui.AnchorType.BELOW, true);
 
   assertEquals('auto', popup.style.left);
@@ -210,7 +248,7 @@
   assertEquals('auto', popup.style.right);
 }
 
-function testBeforeSecondary() {
+/* #export */ function testBeforeSecondary() {
   cr.ui.positionPopupAroundElement(anchor, popup, cr.ui.AnchorType.BEFORE);
 
   assertEquals('100px', popup.style.top);
@@ -224,7 +262,7 @@
   assertEquals('80px', popup.style.bottom);
 }
 
-function testAfterSecondary() {
+/* #export */ function testAfterSecondary() {
   cr.ui.positionPopupAroundElement(anchor, popup, cr.ui.AnchorType.AFTER);
 
   assertEquals('100px', popup.style.top);
@@ -238,7 +276,7 @@
   assertEquals('80px', popup.style.bottom);
 }
 
-function testPositionAtPoint() {
+/* #export */ function testPositionAtPoint() {
   cr.ui.positionPopupAtPoint(100, 100, popup);
 
   assertEquals('100px', popup.style.left);
@@ -260,3 +298,23 @@
   assertEquals('50px', popup.style.right);
   assertEquals('50px', popup.style.bottom);
 }
+
+Object.assign(window, {
+  setUp,
+  tearDown,
+  testAbovePrimary,
+  testBelowPrimary,
+  testBeforePrimary,
+  testBeforePrimaryRtl,
+  testAfterPrimary,
+  testAfterPrimaryRtl,
+  testAboveSecondary,
+  testAboveSecondaryRtl,
+  testAboveSecondarySwappedAlign,
+  testBelowSecondary,
+  testBelowSecondaryRtl,
+  testBelowSecondarySwappedAlign,
+  testBeforeSecondary,
+  testAfterSecondary,
+  testPositionAtPoint,
+});
diff --git a/chrome/test/data/webui/js/cr/ui/splitter_test.html b/chrome/test/data/webui/js/cr/ui/splitter_test.html
index c1cfca8..1989ad9 100644
--- a/chrome/test/data/webui/js/cr/ui/splitter_test.html
+++ b/chrome/test/data/webui/js/cr/ui/splitter_test.html
@@ -1,9 +1,6 @@
 <!doctype html>
 <html>
 <body>
-<div id="previous"></div>
-<div id="splitter"></div>
-<div id="next"></div>
 <script src="chrome://resources/js/cr.js"></script>
 <script src="chrome://resources/js/cr/ui.js"></script>
 <script src="chrome://resources/js/cr/ui/splitter.js"></script>
diff --git a/chrome/test/data/webui/js/cr/ui/splitter_test.js b/chrome/test/data/webui/js/cr/ui/splitter_test.js
index 04c4251..e6e3360 100644
--- a/chrome/test/data/webui/js/cr/ui/splitter_test.js
+++ b/chrome/test/data/webui/js/cr/ui/splitter_test.js
@@ -2,7 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function testSplitter_IgnoresRightMouse() {
+// #import {decorate} from 'chrome://resources/js/cr/ui.m.js';
+// #import {Splitter} from 'chrome://resources/js/cr/ui/splitter.m.js';
+
+/* #export */ function setUp() {
+  const html = `
+    <div id="previous"></div>
+    <div id="splitter"></div>
+    <div id="next"></div>
+  `;
+  document.body.innerHTML = html;
+}
+
+/* #export */ function testSplitter_IgnoresRightMouse() {
   var splitter = document.getElementById('splitter');
   cr.ui.decorate(splitter, cr.ui.Splitter);
 
@@ -15,7 +27,7 @@
   assertTrue(downLeft.defaultPrevented);
 }
 
-function testSplitter_ResizePreviousElement() {
+/* #export */ function testSplitter_ResizePreviousElement() {
   var splitter = document.getElementById('splitter');
   cr.ui.decorate(splitter, cr.ui.Splitter);
   splitter.resizeNextElement = false;
@@ -44,7 +56,7 @@
   assertEquals(100, afterWidth - beforeWidth);
 }
 
-function testSplitter_ResizeNextElement() {
+/* #export */ function testSplitter_ResizeNextElement() {
   var splitter = document.getElementById('splitter');
   cr.ui.decorate(splitter, cr.ui.Splitter, true);
   splitter.resizeNextElement = true;
@@ -69,3 +81,10 @@
   var afterWidth = parseFloat(nextElement.style.width);
   assertEquals(100, afterWidth - beforeWidth);
 }
+
+Object.assign(window, {
+  setUp,
+  testSplitter_IgnoresRightMouse,
+  testSplitter_ResizePreviousElement,
+  testSplitter_ResizeNextElement,
+});
diff --git a/chrome/test/data/webui/webui_resource_browsertest.cc b/chrome/test/data/webui/webui_resource_browsertest.cc
index 5d1c1754..be7f0f1 100644
--- a/chrome/test/data/webui/webui_resource_browsertest.cc
+++ b/chrome/test/data/webui/webui_resource_browsertest.cc
@@ -153,14 +153,33 @@
   LoadTestUrl("js/cr/ui/list_selection_model_test.html");
 }
 
+#if defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, ListSelectionModeModulelTest) {
+  LoadTestUrl("?module=js/cr/ui/list_selection_model_test.m.js");
+}
+#endif
+
 IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, ListSingleSelectionModelTest) {
   LoadTestUrl("js/cr/ui/list_single_selection_model_test.html");
 }
 
+#if defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest,
+                       ListSingleSelectionModelModuleTest) {
+  LoadTestUrl("?module=js/cr/ui/list_single_selection_model_test.m.js");
+}
+#endif
+
 IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, MenuTest) {
   LoadTestUrl("js/cr/ui/menu_test.html");
 }
 
+#if defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, MenuModuleTest) {
+  LoadTestUrl("?module=js/cr/ui/menu_test.m.js");
+}
+#endif
+
 IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, MockTimerTest) {
   LoadTestUrl("mock_timer_test.html");
 }
@@ -173,6 +192,12 @@
   LoadTestUrl("js/cr/ui/position_util_test.html");
 }
 
+#if defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, PositionUtilModuleTest) {
+  LoadTestUrl("?module=js/cr/ui/position_util_test.m.js");
+}
+#endif
+
 IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, CommandTest) {
   LoadTestUrl("js/cr/ui/command_test.html");
 }
@@ -197,10 +222,22 @@
   LoadTestUrl("js/cr/ui/menu_button_test.html");
 }
 
+#if defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, MenuButtonModuleTest) {
+  LoadTestUrl("?module=js/cr/ui/menu_button_test.m.js");
+}
+#endif
+
 IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, SplitterTest) {
   LoadTestUrl("js/cr/ui/splitter_test.html");
 }
 
+#if defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, SplitterModuleTest) {
+  LoadTestUrl("?module=js/cr/ui/splitter_test.m.js");
+}
+#endif
+
 IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, UtilTest) {
   LoadTestUrl("util_test.html");
 }
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 0e5df37..112b1edb 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-13552.0.0
\ No newline at end of file
+13555.0.0
\ No newline at end of file
diff --git a/chromeos/attestation/attestation_flow.cc b/chromeos/attestation/attestation_flow.cc
index 4480a137..73aad54 100644
--- a/chromeos/attestation/attestation_flow.cc
+++ b/chromeos/attestation/attestation_flow.cc
@@ -26,6 +26,22 @@
 
 namespace {
 
+base::Optional<::attestation::CertificateProfile> ProfileToAttestationProtoEnum(
+    AttestationCertificateProfile p) {
+  switch (p) {
+    case PROFILE_ENTERPRISE_MACHINE_CERTIFICATE:
+      return ::attestation::CertificateProfile::ENTERPRISE_MACHINE_CERTIFICATE;
+    case PROFILE_ENTERPRISE_USER_CERTIFICATE:
+      return ::attestation::CertificateProfile::ENTERPRISE_USER_CERTIFICATE;
+    case PROFILE_CONTENT_PROTECTION_CERTIFICATE:
+      return ::attestation::CertificateProfile::CONTENT_PROTECTION_CERTIFICATE;
+    case PROFILE_ENTERPRISE_ENROLLMENT_CERTIFICATE:
+      return ::attestation::CertificateProfile::
+          ENTERPRISE_ENROLLMENT_CERTIFICATE;
+  }
+  return {};
+}
+
 // A reasonable timeout that gives enough time for attestation to be ready,
 // yet does not make the caller wait too long.
 constexpr uint16_t kReadyTimeoutInSeconds = 60;
@@ -67,15 +83,25 @@
 
 AttestationFlow::AttestationFlow(cryptohome::AsyncMethodCaller* async_caller,
                                  CryptohomeClient* cryptohome_client,
-                                 std::unique_ptr<ServerProxy> server_proxy)
+                                 std::unique_ptr<ServerProxy> server_proxy,
+                                 ::attestation::KeyType crypto_key_type)
     : async_caller_(async_caller),
       cryptohome_client_(cryptohome_client),
       attestation_client_(AttestationClient::Get()),
       server_proxy_(std::move(server_proxy)),
+      crypto_key_type_(crypto_key_type),
       ready_timeout_(base::TimeDelta::FromSeconds(kReadyTimeoutInSeconds)),
       retry_delay_(
           base::TimeDelta::FromMilliseconds(kRetryDelayInMilliseconds)) {}
 
+AttestationFlow::AttestationFlow(cryptohome::AsyncMethodCaller* async_caller,
+                                 CryptohomeClient* cryptohome_client,
+                                 std::unique_ptr<ServerProxy> server_proxy)
+    : AttestationFlow(async_caller,
+                      cryptohome_client,
+                      std::move(server_proxy),
+                      ::attestation::KEY_TYPE_RSA) {}
+
 AttestationFlow::~AttestationFlow() = default;
 
 void AttestationFlow::GetCertificate(
@@ -220,12 +246,25 @@
   AttestationKeyType key_type = GetKeyTypeForProfile(certificate_profile);
   if (generate_new_key) {
     // Get the attestation service to create a Privacy CA certificate request.
-    async_caller_->AsyncTpmAttestationCreateCertRequest(
-        server_proxy_->GetType(), certificate_profile,
-        cryptohome::Identification(account_id), request_origin,
-        base::BindOnce(&AttestationFlow::SendCertificateRequestToPCA,
-                       weak_factory_.GetWeakPtr(), key_type, account_id,
-                       key_name, std::move(callback)));
+    const base::Optional<::attestation::CertificateProfile>
+        attestation_profile =
+            ProfileToAttestationProtoEnum(certificate_profile);
+    if (!attestation_profile) {
+      LOG(DFATAL) << "Attestation: Unrecognized profile type: "
+                  << certificate_profile;
+      return;
+    }
+
+    ::attestation::CreateCertificateRequestRequest request;
+    request.set_username(cryptohome::Identification(account_id).id());
+    request.set_certificate_profile(*attestation_profile);
+    request.set_request_origin(request_origin);
+    request.set_key_type(crypto_key_type_);
+
+    attestation_client_->CreateCertificateRequest(
+        request, base::BindOnce(&AttestationFlow::SendCertificateRequestToPCA,
+                                weak_factory_.GetWeakPtr(), key_type,
+                                account_id, key_name, std::move(callback)));
     return;
   }
 
@@ -264,23 +303,25 @@
                           key_name, std::move(callback), true);
 }
 
-void AttestationFlow::SendCertificateRequestToPCA(AttestationKeyType key_type,
-                                                  const AccountId& account_id,
-                                                  const std::string& key_name,
-                                                  CertificateCallback callback,
-                                                  bool success,
-                                                  const std::string& data) {
-  if (!success) {
-    LOG(ERROR) << "Attestation: Failed to create certificate request.";
+void AttestationFlow::SendCertificateRequestToPCA(
+    AttestationKeyType key_type,
+    const AccountId& account_id,
+    const std::string& key_name,
+    CertificateCallback callback,
+    const ::attestation::CreateCertificateRequestReply& reply) {
+  if (reply.status() != ::attestation::STATUS_SUCCESS) {
+    LOG(ERROR) << "Attestation: Failed to create certificate request. Status: "
+               << reply.status();
     std::move(callback).Run(ATTESTATION_UNSPECIFIED_FAILURE, "");
     return;
   }
 
   // Send the request to the Privacy CA.
   server_proxy_->SendCertificateRequest(
-      data, base::BindOnce(&AttestationFlow::SendCertificateResponseToDaemon,
-                           weak_factory_.GetWeakPtr(), key_type, account_id,
-                           key_name, std::move(callback)));
+      reply.pca_request(),
+      base::BindOnce(&AttestationFlow::SendCertificateResponseToDaemon,
+                     weak_factory_.GetWeakPtr(), key_type, account_id, key_name,
+                     std::move(callback)));
 }
 
 void AttestationFlow::SendCertificateResponseToDaemon(
diff --git a/chromeos/attestation/attestation_flow.h b/chromeos/attestation/attestation_flow.h
index 719ffe03..62f45196 100644
--- a/chromeos/attestation/attestation_flow.h
+++ b/chromeos/attestation/attestation_flow.h
@@ -74,6 +74,11 @@
   AttestationFlow(cryptohome::AsyncMethodCaller* async_caller,
                   CryptohomeClient* cryptohome_client,
                   std::unique_ptr<ServerProxy> server_proxy);
+  AttestationFlow(cryptohome::AsyncMethodCaller* async_caller,
+                  CryptohomeClient* cryptohome_client,
+                  std::unique_ptr<ServerProxy> server_proxy,
+                  ::attestation::KeyType crypto_key_type);
+
   virtual ~AttestationFlow();
 
   // Sets the timeout for attestation to be ready.
@@ -241,14 +246,13 @@
   //   account_id - Identifies the active user.
   //   key_name - The name of the key for which a certificate is requested.
   //   callback - Called when the operation completes.
-  //   success - The status of request creation.
-  //   data - The request data for the Privacy CA.
-  void SendCertificateRequestToPCA(AttestationKeyType key_type,
-                                   const AccountId& account_id,
-                                   const std::string& key_name,
-                                   CertificateCallback callback,
-                                   bool success,
-                                   const std::string& data);
+  //   reply - the result returned by |AttestationClient|.
+  void SendCertificateRequestToPCA(
+      AttestationKeyType key_type,
+      const AccountId& account_id,
+      const std::string& key_name,
+      CertificateCallback callback,
+      const ::attestation::CreateCertificateRequestReply& reply);
 
   // Called when the Privacy CA responds to a certificate request.  The response
   // is asynchronously forwarded as-is to the attestation daemon in order to
@@ -295,6 +299,9 @@
   AttestationClient* attestation_client_;
   std::unique_ptr<ServerProxy> server_proxy_;
 
+  // The key type that asks attestation service to create with.
+  const ::attestation::KeyType crypto_key_type_;
+
   base::TimeDelta ready_timeout_;
   base::TimeDelta retry_delay_;
 
diff --git a/chromeos/attestation/attestation_flow_unittest.cc b/chromeos/attestation/attestation_flow_unittest.cc
index be5c81e..142c4ba 100644
--- a/chromeos/attestation/attestation_flow_unittest.cc
+++ b/chromeos/attestation/attestation_flow_unittest.cc
@@ -111,12 +111,18 @@
       .InSequence(flow_order);
 
   const AccountId account_id = AccountId::FromUserEmail("fake@test.com");
-  EXPECT_CALL(async_caller,
-              AsyncTpmAttestationCreateCertRequest(
-                  _, PROFILE_ENTERPRISE_USER_CERTIFICATE,
-                  cryptohome::Identification(account_id), "fake_origin", _))
-      .Times(1)
-      .InSequence(flow_order);
+
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->AllowlistLegacyCreateCertificateRequest(
+          "fake@test.com", "fake_origin",
+          ::attestation::ENTERPRISE_USER_CERTIFICATE,
+          ::attestation::KEY_TYPE_RSA);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->mutable_certificate_request_reply()
+      ->set_pca_request(
+          cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest);
 
   EXPECT_CALL(
       *proxy,
@@ -153,6 +159,95 @@
   RunUntilIdle();
 }
 
+// This is pretty much identical to |GetCertificate| item but during
+// construction the ecc key type is specified.
+TEST_F(AttestationFlowTest, GetCertificate_Ecc) {
+  // Verify the order of calls in a sequence.
+  Sequence flow_order;
+
+  FakeCryptohomeClient client;
+  // Set the enrollment status as |false| so the full enrollment flow is
+  // triggered.
+  client.set_tpm_attestation_is_enrolled(false);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->ConfigureEnrollmentPreparations(true);
+
+  // Use StrictMock when we want to verify invocation frequency.
+  StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
+  async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
+  EXPECT_CALL(async_caller, AsyncTpmAttestationCreateEnrollRequest(_, _))
+      .Times(1)
+      .InSequence(flow_order);
+
+  std::unique_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
+  proxy->DeferToFake(true);
+  EXPECT_CALL(*proxy, GetType()).WillRepeatedly(DoDefault());
+  EXPECT_CALL(
+      *proxy,
+      SendEnrollRequest(
+          cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest, _))
+      .Times(1)
+      .InSequence(flow_order);
+
+  std::string fake_enroll_response =
+      cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest;
+  fake_enroll_response += "_response";
+  EXPECT_CALL(async_caller,
+              AsyncTpmAttestationEnroll(_, fake_enroll_response, _))
+      .Times(1)
+      .InSequence(flow_order);
+
+  const AccountId account_id = AccountId::FromUserEmail("fake@test.com");
+
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->AllowlistLegacyCreateCertificateRequest(
+          "fake@test.com", "fake_origin",
+          ::attestation::ENTERPRISE_USER_CERTIFICATE,
+          ::attestation::KEY_TYPE_ECC);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->mutable_certificate_request_reply()
+      ->set_pca_request(
+          cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest);
+
+  EXPECT_CALL(
+      *proxy,
+      SendCertificateRequest(
+          cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest, _))
+      .Times(1)
+      .InSequence(flow_order);
+
+  std::string fake_cert_response =
+      cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest;
+  fake_cert_response += "_response";
+  EXPECT_CALL(async_caller, AsyncTpmAttestationFinishCertRequest(
+                                fake_cert_response, KEY_USER,
+                                cryptohome::Identification(account_id),
+                                kEnterpriseUserKey, _))
+      .Times(1)
+      .InSequence(flow_order);
+
+  StrictMock<MockObserver> observer;
+  EXPECT_CALL(observer,
+              MockCertificateCallback(
+                  ATTESTATION_SUCCESS,
+                  cryptohome::MockAsyncMethodCaller::kFakeAttestationCert))
+      .Times(1)
+      .InSequence(flow_order);
+  AttestationFlow::CertificateCallback mock_callback = base::BindOnce(
+      &MockObserver::MockCertificateCallback, base::Unretained(&observer));
+
+  std::unique_ptr<ServerProxy> proxy_interface(proxy.release());
+  AttestationFlow flow(&async_caller, &client, std::move(proxy_interface),
+                       ::attestation::KEY_TYPE_ECC);
+  flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, account_id,
+                      "fake_origin", true, std::string() /* key_name */,
+                      std::move(mock_callback));
+  RunUntilIdle();
+}
+
 TEST_F(AttestationFlowTest, GetCertificate_Attestation_Not_Prepared) {
   // Verify the order of calls in a sequence.
   Sequence flow_order;
@@ -189,12 +284,18 @@
       .InSequence(flow_order);
 
   const AccountId account_id = AccountId::FromUserEmail("fake@test.com");
-  EXPECT_CALL(async_caller,
-              AsyncTpmAttestationCreateCertRequest(
-                  _, PROFILE_ENTERPRISE_USER_CERTIFICATE,
-                  cryptohome::Identification(account_id), "fake_origin", _))
-      .Times(1)
-      .InSequence(flow_order);
+
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->AllowlistLegacyCreateCertificateRequest(
+          "fake@test.com", "fake_origin",
+          ::attestation::ENTERPRISE_USER_CERTIFICATE,
+          ::attestation::KEY_TYPE_RSA);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->mutable_certificate_request_reply()
+      ->set_pca_request(
+          cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest);
 
   EXPECT_CALL(
       *proxy,
@@ -417,10 +518,19 @@
 TEST_F(AttestationFlowTest, GetMachineCertificateAlreadyEnrolled) {
   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
   async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
-  EXPECT_CALL(async_caller, AsyncTpmAttestationCreateCertRequest(
-                                _, PROFILE_ENTERPRISE_MACHINE_CERTIFICATE,
-                                cryptohome::Identification(), "", _))
-      .Times(1);
+
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->AllowlistLegacyCreateCertificateRequest(
+          /*username=*/"", /*request_origin=*/"",
+          ::attestation::ENTERPRISE_MACHINE_CERTIFICATE,
+          ::attestation::KEY_TYPE_RSA);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->mutable_certificate_request_reply()
+      ->set_pca_request(
+          cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest);
+
   std::string fake_cert_response =
       cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest;
   fake_cert_response += "_response";
@@ -461,10 +571,18 @@
 TEST_F(AttestationFlowTest, GetEnrollmentCertificateAlreadyEnrolled) {
   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
   async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
-  EXPECT_CALL(async_caller, AsyncTpmAttestationCreateCertRequest(
-                                _, PROFILE_ENTERPRISE_ENROLLMENT_CERTIFICATE,
-                                cryptohome::Identification(), "", _))
-      .Times(1);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->AllowlistLegacyCreateCertificateRequest(
+          /*username=*/"", /*request_origin=*/"",
+          ::attestation::ENTERPRISE_ENROLLMENT_CERTIFICATE,
+          ::attestation::KEY_TYPE_RSA);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->mutable_certificate_request_reply()
+      ->set_pca_request(
+          cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest);
+
   std::string fake_cert_response =
       cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest;
   fake_cert_response += "_response";
@@ -505,10 +623,16 @@
 TEST_F(AttestationFlowTest, GetCertificate_FailCreateCertRequest) {
   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
   async_caller.SetUp(false, cryptohome::MOUNT_ERROR_NONE);
-  EXPECT_CALL(async_caller, AsyncTpmAttestationCreateCertRequest(
-                                _, PROFILE_ENTERPRISE_USER_CERTIFICATE,
-                                cryptohome::Identification(), "", _))
-      .Times(1);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->AllowlistLegacyCreateCertificateRequest(
+          "fake@test.com", "fake_origin",
+          ::attestation::ENTERPRISE_USER_CERTIFICATE,
+          ::attestation::KEY_TYPE_RSA);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->mutable_certificate_request_reply()
+      ->set_status(::attestation::STATUS_UNEXPECTED_DEVICE_ERROR);
 
   chromeos::FakeCryptohomeClient client;
 
@@ -534,12 +658,18 @@
 TEST_F(AttestationFlowTest, GetCertificate_CertRequestRejected) {
   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
   async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
-  EXPECT_CALL(async_caller, AsyncTpmAttestationCreateCertRequest(
-                                _, PROFILE_ENTERPRISE_USER_CERTIFICATE,
-                                cryptohome::Identification(), "", _))
-      .Times(1);
-
   chromeos::FakeCryptohomeClient client;
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->AllowlistLegacyCreateCertificateRequest(
+          /*username=*/"", /*request_origin=*/"",
+          ::attestation::ENTERPRISE_USER_CERTIFICATE,
+          ::attestation::KEY_TYPE_RSA);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->mutable_certificate_request_reply()
+      ->set_pca_request(
+          cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest);
 
   std::unique_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>());
   proxy->DeferToFake(false);
@@ -568,10 +698,18 @@
 TEST_F(AttestationFlowTest, GetCertificate_CertRequestBadRequest) {
   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
   async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
-  EXPECT_CALL(async_caller, AsyncTpmAttestationCreateCertRequest(
-                                _, PROFILE_ENTERPRISE_USER_CERTIFICATE,
-                                cryptohome::Identification(), "", _))
-      .Times(1);
+
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->AllowlistLegacyCreateCertificateRequest(
+          /*username=*/"", /*request_origin=*/"",
+          ::attestation::ENTERPRISE_USER_CERTIFICATE,
+          ::attestation::KEY_TYPE_RSA);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->mutable_certificate_request_reply()
+      ->set_pca_request(
+          cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest);
 
   chromeos::FakeCryptohomeClient client;
 
@@ -634,10 +772,17 @@
 TEST_F(AttestationFlowTest, GetCertificate_CheckExisting) {
   StrictMock<cryptohome::MockAsyncMethodCaller> async_caller;
   async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE);
-  EXPECT_CALL(async_caller, AsyncTpmAttestationCreateCertRequest(
-                                _, PROFILE_ENTERPRISE_USER_CERTIFICATE,
-                                cryptohome::Identification(), "", _))
-      .Times(1);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->AllowlistLegacyCreateCertificateRequest(
+          /*username=*/"", /*request_origin=*/"",
+          ::attestation::ENTERPRISE_USER_CERTIFICATE,
+          ::attestation::KEY_TYPE_RSA);
+  chromeos::AttestationClient::Get()
+      ->GetTestInterface()
+      ->mutable_certificate_request_reply()
+      ->set_pca_request(
+          cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest);
   std::string fake_cert_response =
       cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest;
   fake_cert_response += "_response";
diff --git a/chromeos/components/media_app_ui/resources/index.html b/chromeos/components/media_app_ui/resources/index.html
index cbb8414..79c23e1 100644
--- a/chromeos/components/media_app_ui/resources/index.html
+++ b/chromeos/components/media_app_ui/resources/index.html
@@ -5,6 +5,14 @@
 <html dir="$i18n{textdirection}" lang="$i18n{language}">
 <meta charset="utf-8">
 <title>$i18n{appTitle}</title>
+<link rel="icon" type="image/png" sizes="16x16" href="system_assets/app_icon_16.png">
+<link rel="icon" type="image/png" sizes="32x32" href="system_assets/app_icon_32.png">
+<link rel="icon" type="image/png" sizes="48x48" href="system_assets/app_icon_48.png">
+<link rel="icon" type="image/png" sizes="64x64" href="system_assets/app_icon_64.png">
+<link rel="icon" type="image/png" sizes="96x96" href="system_assets/app_icon_96.png">
+<link rel="icon" type="image/png" sizes="128x128" href="system_assets/app_icon_128.png">
+<link rel="icon" type="image/png" sizes="192x192" href="system_assets/app_icon_192.png">
+<link rel="icon" type="image/png" sizes="256x256" href="system_assets/app_icon_256.png">
 <style>
   body {
     background-color: #202124;
diff --git a/chromeos/components/sensors/fake_sensor_device.cc b/chromeos/components/sensors/fake_sensor_device.cc
index 2bef992c..c0c88d6 100644
--- a/chromeos/components/sensors/fake_sensor_device.cc
+++ b/chromeos/components/sensors/fake_sensor_device.cc
@@ -4,11 +4,11 @@
 
 #include "chromeos/components/sensors/fake_sensor_device.h"
 
-#include <algorithm>
 #include <utility>
 
 #include "base/bind.h"
 #include "base/containers/flat_map.h"
+#include "base/ranges/algorithm.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 
 namespace chromeos {
@@ -21,34 +21,54 @@
     const FakeSensorDevice::ChannelData&) = default;
 FakeSensorDevice::ChannelData::~ChannelData() = default;
 
-FakeSensorDevice::FakeSensorDevice() {
+FakeSensorDevice::FakeSensorDevice(const std::vector<ChannelData>& channels)
+    : channels_(channels) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  for (auto& client : clients_)
+    client.second.channels_enabled.assign(channels_.size(), false);
 }
 
 FakeSensorDevice::~FakeSensorDevice() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
-bool FakeSensorDevice::is_bound() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  return receiver_.is_bound();
-}
-
-void FakeSensorDevice::Bind(
+mojo::ReceiverId FakeSensorDevice::AddReceiver(
     mojo::PendingReceiver<mojom::SensorDevice> pending_receiver) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(!is_bound());
 
-  receiver_.Bind(std::move(pending_receiver));
-  receiver_.set_disconnect_handler(base::BindOnce(
-      &FakeSensorDevice::OnDeviceDisconnect, base::Unretained(this)));
+  auto id = receiver_set_.Add(this, std::move(pending_receiver));
+  DCHECK(clients_.find(id) == clients_.end());
+  clients_[id].channels_enabled.assign(channels_.size(), false);
+
+  return id;
 }
 
-void FakeSensorDevice::OnDeviceDisconnect() {
+void FakeSensorDevice::RemoveReceiver(mojo::ReceiverId id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(receiver_set_.HasReceiver(id));
+
+  clients_.erase(id);
+  receiver_set_.Remove(id);
+}
+
+void FakeSensorDevice::ClearReceivers() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  receiver_.reset();
+  clients_.clear();
+  receiver_set_.Clear();
+}
+
+bool FakeSensorDevice::HasReceivers() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  return !receiver_set_.empty();
+}
+
+size_t FakeSensorDevice::SizeOfReceivers() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  return receiver_set_.size();
 }
 
 void FakeSensorDevice::SetAttribute(const std::string& attr_name,
@@ -58,12 +78,14 @@
   attributes_[attr_name] = attr_value;
 }
 
-void FakeSensorDevice::SetChannels(const std::vector<ChannelData>& channels) {
+void FakeSensorDevice::ResetObserverRemote(mojo::ReceiverId id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(channels_.empty());
 
-  channels_ = channels;
-  channels_enabled_.assign(channels_.size(), false);
+  auto it = clients_.find(id);
+  if (it == clients_.end())
+    return;
+
+  it->second.observer.reset();
 }
 
 void FakeSensorDevice::GetAttributes(const std::vector<std::string>& attr_names,
@@ -91,19 +113,23 @@
   if (frequency < 0.0)
     frequency = 0.0;
 
-  frequency_ = frequency;
+  auto& client = clients_[receiver_set_.current_receiver()];
+
+  client.frequency = frequency;
   base::SequencedTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), std::move(frequency)));
 
-  if (ReadyToSendSample())
-    SendSample();
+  SendSampleIfReady(client);
 }
 
 void FakeSensorDevice::StartReadingSamples(
     mojo::PendingRemote<mojom::SensorDeviceSamplesObserver> observer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (observer_.is_bound()) {
+  auto id = receiver_set_.current_receiver();
+  auto& client = clients_[id];
+
+  if (client.observer.is_bound()) {
     mojo::Remote<mojom::SensorDeviceSamplesObserver> remote(
         std::move(observer));
     remote->OnErrorOccurred(mojom::ObserverErrorType::ALREADY_STARTED);
@@ -111,27 +137,30 @@
     return;
   }
 
-  observer_.Bind(std::move(observer));
-  // Reuse StopReadingSamples to reset |observer_|.
-  observer_.set_disconnect_handler(base::BindOnce(
-      &FakeSensorDevice::StopReadingSamples, base::Unretained(this)));
+  client.observer.Bind(std::move(observer));
+  client.observer.set_disconnect_handler(base::BindOnce(
+      &FakeSensorDevice::ResetObserverRemote, base::Unretained(this), id));
 
-  if (!frequency_.has_value() || frequency_.value() <= 0.0) {
-    observer_->OnErrorOccurred(mojom::ObserverErrorType::FREQUENCY_INVALID);
+  if (!client.frequency.has_value() || client.frequency.value() <= 0.0) {
+    client.observer->OnErrorOccurred(
+        mojom::ObserverErrorType::FREQUENCY_INVALID);
+    return;
   }
 
-  if (!std::any_of(channels_enabled_.begin(), channels_enabled_.end(),
-                   [](bool en) { return en; }))
-    observer_->OnErrorOccurred(mojom::ObserverErrorType::NO_ENABLED_CHANNELS);
+  if (base::ranges::none_of(client.channels_enabled,
+                            [](bool enabled) { return enabled; })) {
+    client.observer->OnErrorOccurred(
+        mojom::ObserverErrorType::NO_ENABLED_CHANNELS);
+    return;
+  }
 
-  if (ReadyToSendSample())
-    SendSample();
+  SendSampleIfReady(client);
 }
 
 void FakeSensorDevice::StopReadingSamples() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  observer_.reset();
+  clients_[receiver_set_.current_receiver()].observer.reset();
 }
 
 void FakeSensorDevice::GetAllChannelIds(GetAllChannelIdsCallback callback) {
@@ -151,22 +180,23 @@
     SetChannelsEnabledCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
+  auto& client = clients_[receiver_set_.current_receiver()];
+
   std::vector<int32_t> failed_indices;
   for (int32_t index : iio_chn_indices) {
-    if (static_cast<size_t>(index) >= channels_enabled_.size()) {
+    if (static_cast<size_t>(index) >= client.channels_enabled.size()) {
       failed_indices.push_back(index);
       continue;
     }
 
-    channels_enabled_[index] = en;
+    client.channels_enabled[index] = en;
   }
 
   base::SequencedTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
       base::BindOnce(std::move(callback), std::move(failed_indices)));
 
-  if (ReadyToSendSample())
-    SendSample();
+  SendSampleIfReady(client);
 }
 
 void FakeSensorDevice::GetChannelsEnabled(
@@ -174,14 +204,16 @@
     GetChannelsEnabledCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
+  auto& client = clients_[receiver_set_.current_receiver()];
+
   std::vector<bool> enabled;
   for (int32_t index : iio_chn_indices) {
-    if (static_cast<size_t>(index) >= channels_enabled_.size()) {
+    if (static_cast<size_t>(index) >= client.channels_enabled.size()) {
       enabled.push_back(false);
       continue;
     }
 
-    enabled.push_back(channels_enabled_[index]);
+    enabled.push_back(client.channels_enabled[index]);
   }
 
   base::SequencedTaskRunnerHandle::Get()->PostTask(
@@ -210,33 +242,31 @@
       FROM_HERE, base::BindOnce(std::move(callback), std::move(attrs)));
 }
 
-bool FakeSensorDevice::ReadyToSendSample() {
+FakeSensorDevice::ClientData::ClientData() = default;
+FakeSensorDevice::ClientData::~ClientData() = default;
+
+void FakeSensorDevice::SendSampleIfReady(ClientData& client) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_EQ(channels_.size(), client.channels_enabled.size());
 
-  if (!observer_.is_bound())
-    return false;
+  if (!client.observer.is_bound())
+    return;
 
-  if (!frequency_.has_value() || frequency_.value() <= 0.0)
-    return false;
-
-  return std::any_of(channels_enabled_.begin(), channels_enabled_.end(),
-                     [](bool en) { return en; });
-}
-
-void FakeSensorDevice::SendSample() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(ReadyToSendSample());
-  CHECK_EQ(channels_.size(), channels_enabled_.size());
+  if (!client.frequency.has_value() || client.frequency.value() <= 0.0)
+    return;
 
   base::flat_map<int32_t, int64_t> sample;
   for (size_t i = 0; i < channels_.size(); ++i) {
-    if (!channels_enabled_[i])
+    if (!client.channels_enabled[i])
       continue;
 
     sample[i] = channels_[i].sample_data;
   }
 
-  observer_->OnSampleUpdated(std::move(sample));
+  if (sample.empty())
+    return;
+
+  client.observer->OnSampleUpdated(std::move(sample));
 }
 
 }  // namespace sensors
diff --git a/chromeos/components/sensors/fake_sensor_device.h b/chromeos/components/sensors/fake_sensor_device.h
index ee421e2..3ab6e761 100644
--- a/chromeos/components/sensors/fake_sensor_device.h
+++ b/chromeos/components/sensors/fake_sensor_device.h
@@ -13,7 +13,7 @@
 #include "base/optional.h"
 #include "base/sequence_checker.h"
 #include "chromeos/components/sensors/mojom/sensor.mojom.h"
-#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
 namespace chromeos {
@@ -32,19 +32,23 @@
     int64_t sample_data;
   };
 
-  FakeSensorDevice();
+  explicit FakeSensorDevice(const std::vector<ChannelData>& channels);
   FakeSensorDevice(const FakeSensorDevice&) = delete;
   FakeSensorDevice& operator=(const FakeSensorDevice&) = delete;
   ~FakeSensorDevice() override;
 
-  bool is_bound();
-  void Bind(mojo::PendingReceiver<mojom::SensorDevice> pending_receiver);
-  void OnDeviceDisconnect();
+  mojo::ReceiverId AddReceiver(
+      mojo::PendingReceiver<mojom::SensorDevice> pending_receiver);
+  void RemoveReceiver(mojo::ReceiverId id);
+
+  void ClearReceivers();
+  bool HasReceivers() const;
+  size_t SizeOfReceivers() const;
 
   void SetAttribute(const std::string& attr_name,
                     const std::string& attr_value);
 
-  void SetChannels(const std::vector<ChannelData>& channels);
+  void ResetObserverRemote(mojo::ReceiverId id);
 
   // Implementation of mojom::SensorDevice.
   void SetTimeout(uint32_t timeout) override {}
@@ -66,17 +70,25 @@
                              GetChannelsAttributesCallback callback) override;
 
  private:
-  bool ReadyToSendSample();
-  void SendSample();
+  struct ClientData {
+    ClientData();
+    ~ClientData();
+
+    base::Optional<double> frequency;
+    std::vector<bool> channels_enabled;
+    mojo::Remote<mojom::SensorDeviceSamplesObserver> observer;
+  };
+
+  void SendSampleIfReady(ClientData& client);
 
   std::map<std::string, std::string> attributes_;
-  base::Optional<double> frequency_;
-  std::vector<ChannelData> channels_;
-  std::vector<bool> channels_enabled_;
+  const std::vector<ChannelData> channels_;
 
-  mojo::Remote<mojom::SensorDeviceSamplesObserver> observer_;
+  mojo::ReceiverSet<mojom::SensorDevice> receiver_set_;
 
-  mojo::Receiver<mojom::SensorDevice> receiver_{this};
+  // First is the client's id from |receiver_set_|, second is the client's
+  // states and observer remote.
+  std::map<mojo::ReceiverId, ClientData> clients_;
 
   SEQUENCE_CHECKER(sequence_checker_);
 };
diff --git a/chromeos/components/sensors/fake_sensor_service.cc b/chromeos/components/sensors/fake_sensor_service.cc
index 991aff4..5f013eff 100644
--- a/chromeos/components/sensors/fake_sensor_service.cc
+++ b/chromeos/components/sensors/fake_sensor_service.cc
@@ -94,7 +94,7 @@
   if (it == devices_.end())
     return;
 
-  it->second.sensor_device->Bind(std::move(device_request));
+  it->second.sensor_device->AddReceiver(std::move(device_request));
 }
 
 FakeSensorService::DeviceData::DeviceData() = default;
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index 66ecf4d..3a74bc8 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -435,6 +435,11 @@
 // ChromeOS Media App. https://crbug.com/996088.
 const base::Feature kMediaApp{"MediaApp", base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Whether known extensions for RAW image formats are handled by the ChromeOS
+// Media App.
+const base::Feature kMediaAppHandlesRaw{"MediaAppHandlesRaw",
+                                        base::FEATURE_ENABLED_BY_DEFAULT};
+
 // Enables a unique URL for each path in CrOS settings.
 // This allows deep linking to individual settings, i.e. in settings search.
 const base::Feature kOsSettingsDeepLinking{"OsSettingsDeepLinking",
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index e01358b1..2384ec7 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -196,6 +196,8 @@
 extern const base::Feature kLoginDisplayPasswordButton;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kMediaApp;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+extern const base::Feature kMediaAppHandlesRaw;
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kMinimumChromeVersion;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kOsSettingsDeepLinking;
diff --git a/chromeos/crosapi/mojom/OWNERS b/chromeos/crosapi/mojom/OWNERS
index 212b2802..f4d24e5d 100644
--- a/chromeos/crosapi/mojom/OWNERS
+++ b/chromeos/crosapi/mojom/OWNERS
@@ -1,8 +1,17 @@
 per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
-# Prefer Chrome OS owners for large changes to the Lacros API.
+
+# For small changes, like adding a field to an existing API, prefer
+# Lacros owners. See go/lacros-mojo-security-review
+per-file *.mojom=file://chromeos/LACROS_OWNERS
+
+# Prefer Chrome OS owners for larger or security-sensitive changes
+# to the Lacros API. See go/lacros-mojo-security-review
 per-file *.mojom=file://chromeos/SECURITY_OWNERS
 
+# General Chrome IPC owners are a last resort.
+per-file *.mojom=file://ipc/SECURITY_OWNERS
+
 per-file *_mojom_traits*.*=set noparent
-per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *.mojom_traits*.*=file://chromeos/LACROS_OWNERS
 per-file *.mojom_traits*.*=file://chromeos/SECURITY_OWNERS
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromeos/dbus/attestation/attestation_client.h b/chromeos/dbus/attestation/attestation_client.h
index cb95c72..20976b5 100644
--- a/chromeos/dbus/attestation/attestation_client.h
+++ b/chromeos/dbus/attestation/attestation_client.h
@@ -92,10 +92,24 @@
         ::attestation::AttestationStatus status) = 0;
 
     // Allowlists |request| so the certificate requests that comes in afterwards
-    // will get a fake certificate. if any alias of |request| has been
+    // will get a fake certificate. If any alias of |request| has been
     // allowlisted this functions performs no-ops.
     virtual void AllowlistCertificateRequest(
         const ::attestation::GetCertificateRequest& request) = 0;
+
+    // Allowlists the request that has |username|, |request_origin|, |profile|,
+    // and |key_type|, so the certificate requests that comes in afterwards will
+    // be successfully created.
+    virtual void AllowlistLegacyCreateCertificateRequest(
+        const std::string& username,
+        const std::string& request_origin,
+        ::attestation::CertificateProfile profile,
+        ::attestation::KeyType key_type) = 0;
+
+    // Gets the mutable |CreateCertificateRequestReply| that is returned when
+    // queried.
+    virtual ::attestation::CreateCertificateRequestReply*
+    mutable_certificate_request_reply() = 0;
   };
 
   // Not copyable or movable.
diff --git a/chromeos/dbus/attestation/fake_attestation_client.cc b/chromeos/dbus/attestation/fake_attestation_client.cc
index 3e5a2f6..04d85828 100644
--- a/chromeos/dbus/attestation/fake_attestation_client.cc
+++ b/chromeos/dbus/attestation/fake_attestation_client.cc
@@ -49,6 +49,11 @@
 
 FakeAttestationClient::~FakeAttestationClient() = default;
 
+::attestation::CreateCertificateRequestReply*
+FakeAttestationClient::mutable_certificate_request_reply() {
+  return &certificate_request_reply_;
+}
+
 void FakeAttestationClient::GetKeyInfo(
     const ::attestation::GetKeyInfoRequest& request,
     GetKeyInfoCallback callback) {
@@ -153,7 +158,18 @@
 void FakeAttestationClient::CreateCertificateRequest(
     const ::attestation::CreateCertificateRequestRequest& request,
     CreateCertificateRequestCallback callback) {
-  NOTIMPLEMENTED();
+  for (const auto& req : allowlisted_create_requests_) {
+    if (req.username() == request.username() &&
+        req.request_origin() == request.request_origin() &&
+        req.certificate_profile() == request.certificate_profile() &&
+        req.key_type() == request.key_type()) {
+      PostProtoResponse(std::move(callback), certificate_request_reply_);
+      return;
+    }
+  }
+  ::attestation::CreateCertificateRequestReply failed_reply;
+  failed_reply.set_status(::attestation::STATUS_UNEXPECTED_DEVICE_ERROR);
+  PostProtoResponse(std::move(callback), failed_reply);
 }
 
 void FakeAttestationClient::FinishCertificateRequest(
@@ -267,6 +283,19 @@
   certificate_indices_.push_back(kCertificateNotAssigned);
 }
 
+void FakeAttestationClient::AllowlistLegacyCreateCertificateRequest(
+    const std::string& username,
+    const std::string& request_origin,
+    ::attestation::CertificateProfile profile,
+    ::attestation::KeyType key_type) {
+  ::attestation::CreateCertificateRequestRequest request;
+  request.set_username(username);
+  request.set_request_origin(request_origin);
+  request.set_certificate_profile(profile);
+  request.set_key_type(key_type);
+  allowlisted_create_requests_.push_back(request);
+}
+
 AttestationClient::TestInterface* FakeAttestationClient::GetTestInterface() {
   return this;
 }
diff --git a/chromeos/dbus/attestation/fake_attestation_client.h b/chromeos/dbus/attestation/fake_attestation_client.h
index 1c59a89..73960d2 100644
--- a/chromeos/dbus/attestation/fake_attestation_client.h
+++ b/chromeos/dbus/attestation/fake_attestation_client.h
@@ -99,6 +99,13 @@
       ::attestation::AttestationStatus status) override;
   void AllowlistCertificateRequest(
       const ::attestation::GetCertificateRequest& request) override;
+  void AllowlistLegacyCreateCertificateRequest(
+      const std::string& username,
+      const std::string& request_origin,
+      ::attestation::CertificateProfile profile,
+      ::attestation::KeyType key_type) override;
+  ::attestation::CreateCertificateRequestReply*
+  mutable_certificate_request_reply() override;
 
   AttestationClient::TestInterface* GetTestInterface() override;
 
@@ -110,8 +117,15 @@
 
   bool is_enrolled_ = false;
 
+  ::attestation::CreateCertificateRequestReply certificate_request_reply_;
+
   // Maintains the allowlisted certificate requests.
   std::vector<::attestation::GetCertificateRequest> allowlisted_requests_;
+
+  // Maintains the allowlisted legacy create-certificate requests.
+  std::vector<::attestation::CreateCertificateRequestRequest>
+      allowlisted_create_requests_;
+
   // Maintains the numbers assigned to the allowlisted requests.
   std::vector<int> certificate_indices_;
   // The count of certificates that has been issued.
diff --git a/chromeos/dbus/cryptohome/cryptohome_client.cc b/chromeos/dbus/cryptohome/cryptohome_client.cc
index 7241560..2fbcae82 100644
--- a/chromeos/dbus/cryptohome/cryptohome_client.cc
+++ b/chromeos/dbus/cryptohome/cryptohome_client.cc
@@ -482,14 +482,6 @@
   }
 
   // CryptohomeClient override.
-  void TpmAttestationIsPrepared(DBusMethodCallback<bool> callback) override {
-    dbus::MethodCall method_call(
-        cryptohome::kCryptohomeInterface,
-        cryptohome::kCryptohomeTpmIsAttestationPrepared);
-    return CallBoolMethod(&method_call, std::move(callback));
-  }
-
-  // CryptohomeClient override.
   void TpmAttestationGetEnrollmentId(
       bool ignore_cache,
       DBusMethodCallback<TpmAttestationDataResult> callback) override {
diff --git a/chromeos/dbus/cryptohome/cryptohome_client.h b/chromeos/dbus/cryptohome/cryptohome_client.h
index e3c72ee..564f7d30 100644
--- a/chromeos/dbus/cryptohome/cryptohome_client.h
+++ b/chromeos/dbus/cryptohome/cryptohome_client.h
@@ -316,10 +316,6 @@
   // succeeds. This method blocks until the call returns.
   virtual bool InstallAttributesIsFirstInstall(bool* is_first_install) = 0;
 
-  // Calls the TpmAttestationIsPrepared dbus method.  The callback is called
-  // when the operation completes.
-  virtual void TpmAttestationIsPrepared(DBusMethodCallback<bool> callback) = 0;
-
   // Requests the device's enrollment identifier (EID). The |callback| will be
   // called with the EID. If |ignore_cache| is true, the EID is calculated
   // even if the attestation database already contains a cached version.
diff --git a/chromeos/dbus/cryptohome/fake_cryptohome_client.cc b/chromeos/dbus/cryptohome/fake_cryptohome_client.cc
index 179ad223..089a71e 100644
--- a/chromeos/dbus/cryptohome/fake_cryptohome_client.cc
+++ b/chromeos/dbus/cryptohome/fake_cryptohome_client.cc
@@ -332,15 +332,6 @@
   return true;
 }
 
-void FakeCryptohomeClient::TpmAttestationIsPrepared(
-    DBusMethodCallback<bool> callback) {
-  auto result = service_is_available_
-                    ? base::make_optional(tpm_attestation_is_prepared_)
-                    : base::nullopt;
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback), result));
-}
-
 void FakeCryptohomeClient::TpmAttestationGetEnrollmentId(
     bool ignore_cache,
     DBusMethodCallback<TpmAttestationDataResult> callback) {
diff --git a/chromeos/dbus/cryptohome/fake_cryptohome_client.h b/chromeos/dbus/cryptohome/fake_cryptohome_client.h
index 99a2663..dc28b6a75 100644
--- a/chromeos/dbus/cryptohome/fake_cryptohome_client.h
+++ b/chromeos/dbus/cryptohome/fake_cryptohome_client.h
@@ -99,7 +99,6 @@
   void InstallAttributesIsReady(DBusMethodCallback<bool> callback) override;
   bool InstallAttributesIsInvalid(bool* is_invalid) override;
   bool InstallAttributesIsFirstInstall(bool* is_first_install) override;
-  void TpmAttestationIsPrepared(DBusMethodCallback<bool> callback) override;
   void TpmAttestationGetEnrollmentId(
       bool ignore_cache,
       DBusMethodCallback<TpmAttestationDataResult> callback) override;
@@ -327,10 +326,6 @@
     tpm_attestation_is_enrolled_ = enrolled;
   }
 
-  void set_tpm_attestation_is_prepared(bool prepared) {
-    tpm_attestation_is_prepared_ = prepared;
-  }
-
   void set_tpm_attestation_does_key_exist_should_succeed(bool should_succeed) {
     tpm_attestation_does_key_exist_should_succeed_ = should_succeed;
   }
@@ -502,7 +497,6 @@
   std::string tpm_attestation_enrollment_id_ =
       "6fcc0ebddec3db95cdcf82476d594f4d60db934c5b47fa6085c707b2a93e205b";
   bool tpm_attestation_is_enrolled_ = true;
-  bool tpm_attestation_is_prepared_ = true;
   bool tpm_attestation_does_key_exist_should_succeed_ = true;
   bool supports_low_entropy_credentials_ = false;
   // Controls if CheckKeyEx actually checks the key.
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt
index 39309a54..fc09563 100644
--- a/chromeos/profiles/atom.afdo.newest.txt
+++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-atom-88-4280.20-1603104419-benchmark-88.0.4300.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-atom-88-4280.20-1603104419-benchmark-88.0.4303.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt
index 3405f6a5..a3fe763d 100644
--- a/chromeos/profiles/bigcore.afdo.newest.txt
+++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-bigcore-88-4280.20-1603100572-benchmark-88.0.4300.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-bigcore-88-4280.20-1603100572-benchmark-88.0.4303.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt
index a8e85153..40ed6626 100644
--- a/chromeos/profiles/orderfile.newest.txt
+++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@
-chromeos-chrome-orderfile-field-88-4280.20-1603104419-benchmark-88.0.4296.6-r1.orderfile.xz
+chromeos-chrome-orderfile-field-88-4280.20-1603104419-benchmark-88.0.4300.0-r1.orderfile.xz
diff --git a/chromeos/services/ime/decoder/decoder_engine.cc b/chromeos/services/ime/decoder/decoder_engine.cc
index bd736a0..e224b68f9 100644
--- a/chromeos/services/ime/decoder/decoder_engine.cc
+++ b/chromeos/services/ime/decoder/decoder_engine.cc
@@ -138,11 +138,12 @@
          engine_main_entry_->IsImeSupported(ime_spec.c_str());
 }
 
-void DecoderEngine::OnFocus() {
+void DecoderEngine::OnFocus(mojom::InputFieldInfoPtr input_field_info) {
   const uint64_t seq_id = current_seq_id_;
   ++current_seq_id_;
 
-  ProcessMessage(WrapAndSerializeMessage(OnFocusToProto(seq_id)),
+  ProcessMessage(WrapAndSerializeMessage(
+                     OnFocusToProto(seq_id, std::move(input_field_info))),
                  base::DoNothing());
 }
 
@@ -177,6 +178,14 @@
                  base::DoNothing());
 }
 
+void DecoderEngine::OnCompositionCanceled() {
+  const uint64_t seq_id = current_seq_id_;
+  ++current_seq_id_;
+
+  ProcessMessage(WrapAndSerializeMessage(OnCompositionCanceledToProto(seq_id)),
+                 base::DoNothing());
+}
+
 void DecoderEngine::ProcessMessage(const std::vector<uint8_t>& message,
                                    ProcessMessageCallback callback) {
   // TODO(https://crbug.com/837156): Set a default protobuf message.
diff --git a/chromeos/services/ime/decoder/decoder_engine.h b/chromeos/services/ime/decoder/decoder_engine.h
index 2296c7e3f..35047a0 100644
--- a/chromeos/services/ime/decoder/decoder_engine.h
+++ b/chromeos/services/ime/decoder/decoder_engine.h
@@ -32,7 +32,7 @@
 
   void ProcessMessage(const std::vector<uint8_t>& message,
                       ProcessMessageCallback callback) override;
-  void OnFocus() override;
+  void OnFocus(mojom::InputFieldInfoPtr input_field_info) override;
   void OnBlur() override;
   void OnKeyEvent(mojom::PhysicalKeyEventPtr event,
                   OnKeyEventCallback callback) override;
@@ -40,6 +40,7 @@
       const std::string& text,
       uint32_t offset,
       mojom::SelectionRangePtr selection_range) override;
+  void OnCompositionCanceled() override;
 
  private:
   // Try to load the decoding functions from some decoder shared library.
diff --git a/chromeos/services/ime/decoder/decoder_engine_unittest.cc b/chromeos/services/ime/decoder/decoder_engine_unittest.cc
index 7bf4fdf1..1196449e 100644
--- a/chromeos/services/ime/decoder/decoder_engine_unittest.cc
+++ b/chromeos/services/ime/decoder/decoder_engine_unittest.cc
@@ -53,7 +53,7 @@
                       ProcessMessageCallback callback) final {
     std::move(callback).Run({});
   }
-  void OnFocus() final {}
+  void OnFocus(mojom::InputFieldInfoPtr input_field_info) final {}
   void OnBlur() final {}
   void ProcessKeypressForRulebased(
       ime::mojom::PhysicalKeyEventPtr event,
@@ -64,6 +64,7 @@
       const std::string& text,
       uint32_t offset,
       ime::mojom::SelectionRangePtr selection_range) final {}
+  void OnCompositionCanceled() final {}
   void ResetForRulebased() final {}
   void GetRulebasedKeypressCountForTesting(
       GetRulebasedKeypressCountForTestingCallback callback) final {}
@@ -109,12 +110,18 @@
   mojo::Remote<mojom::InputChannel> client;
   ASSERT_TRUE(engine.BindRequest(kImeSpec, client.BindNewPipeAndPassReceiver(),
                                  receiver.BindNewPipeAndPassRemote(), {}));
+
+  auto info = mojom::InputFieldInfo::New(mojom::InputFieldType::kNumber,
+                                         mojom::AutocorrectMode::kEnabled,
+                                         mojom::PersonalizationMode::kEnabled);
+
   ime::Wrapper expected_proto;
-  *expected_proto.mutable_public_message() = OnFocusToProto(/*seq_id=*/0);
+  *expected_proto.mutable_public_message() =
+      OnFocusToProto(/*seq_id=*/0, info.Clone());
 
   EXPECT_CALL(mock_main_entry_, Process).With(EqualsProto(expected_proto));
 
-  client->OnFocus();
+  client->OnFocus(info.Clone());
   client.FlushForTesting();
 }
 
@@ -188,5 +195,22 @@
   client.FlushForTesting();
 }
 
+TEST_F(DecoderEngineTest, OnCompositionCanceledSendsMessageToSharedLib) {
+  DecoderEngine engine(/*platform=*/nullptr);
+  StubInputChannel stub_channel;
+  mojo::Receiver<mojom::InputChannel> receiver(&stub_channel);
+  mojo::Remote<mojom::InputChannel> client;
+  ASSERT_TRUE(engine.BindRequest(kImeSpec, client.BindNewPipeAndPassReceiver(),
+                                 receiver.BindNewPipeAndPassRemote(), {}));
+  ime::Wrapper expected_proto;
+  *expected_proto.mutable_public_message() =
+      OnCompositionCanceledToProto(/*seq_id=*/0);
+
+  EXPECT_CALL(mock_main_entry_, Process).With(EqualsProto(expected_proto));
+
+  client->OnCompositionCanceled();
+  client.FlushForTesting();
+}
+
 }  // namespace ime
 }  // namespace chromeos
diff --git a/chromeos/services/ime/decoder/proto_conversion.cc b/chromeos/services/ime/decoder/proto_conversion.cc
index 576c8ade..f497c2e 100644
--- a/chromeos/services/ime/decoder/proto_conversion.cc
+++ b/chromeos/services/ime/decoder/proto_conversion.cc
@@ -19,13 +19,61 @@
   return result;
 }
 
+InputFieldInfo::InputFieldType InputFieldTypeToProto(
+    mojom::InputFieldType input_field_type) {
+  switch (input_field_type) {
+    case mojom::InputFieldType::kNoIME:
+      return InputFieldInfo::INPUT_FIELD_TYPE_NO_IME;
+    case mojom::InputFieldType::kText:
+      return InputFieldInfo::INPUT_FIELD_TYPE_TEXT;
+    case mojom::InputFieldType::kSearch:
+      return InputFieldInfo::INPUT_FIELD_TYPE_SEARCH;
+    case mojom::InputFieldType::kTelephone:
+      return InputFieldInfo::INPUT_FIELD_TYPE_TELEPHONE;
+    case mojom::InputFieldType::kURL:
+      return InputFieldInfo::INPUT_FIELD_TYPE_URL;
+    case mojom::InputFieldType::kEmail:
+      return InputFieldInfo::INPUT_FIELD_TYPE_EMAIL;
+    case mojom::InputFieldType::kNumber:
+      return InputFieldInfo::INPUT_FIELD_TYPE_NUMBER;
+    case mojom::InputFieldType::kPassword:
+      return InputFieldInfo::INPUT_FIELD_TYPE_PASSWORD;
+  }
+}
+
+InputFieldInfo::AutocorrectMode AutocorrectModeToProto(
+    mojom::AutocorrectMode autocorrect_mode) {
+  switch (autocorrect_mode) {
+    case mojom::AutocorrectMode::kDisabled:
+      return InputFieldInfo::AUTOCORRECT_MODE_DISABLED;
+    case mojom::AutocorrectMode::kEnabled:
+      return InputFieldInfo::AUTOCORRECT_MODE_ENABLED;
+  }
+}
+
+InputFieldInfo::PersonalizationMode PersonalizationModeToProto(
+    mojom::PersonalizationMode personalization_mode) {
+  switch (personalization_mode) {
+    case mojom::PersonalizationMode::kDisabled:
+      return InputFieldInfo::PERSONALIZATION_MODE_DISABLED;
+    case mojom::PersonalizationMode::kEnabled:
+      return InputFieldInfo::PERSONALIZATION_MODE_ENABLED;
+  }
+}
+
 }  // namespace
 
-ime::PublicMessage OnFocusToProto(uint64_t seq_id) {
+ime::PublicMessage OnFocusToProto(uint64_t seq_id,
+                                  mojom::InputFieldInfoPtr input_field_info) {
   ime::PublicMessage message;
   message.set_seq_id(seq_id);
 
-  *message.mutable_on_focus() = ime::OnFocus();
+  ime::InputFieldInfo& proto_info = *message.mutable_on_focus()->mutable_info();
+  proto_info.set_type(InputFieldTypeToProto(input_field_info->type));
+  proto_info.set_autocorrect(
+      AutocorrectModeToProto(input_field_info->autocorrect));
+  proto_info.set_personalization(
+      PersonalizationModeToProto(input_field_info->personalization));
   return message;
 }
 
@@ -72,5 +120,14 @@
   return message;
 }
 
+ime::PublicMessage OnCompositionCanceledToProto(uint64_t seq_id) {
+  ime::PublicMessage message;
+  message.set_seq_id(seq_id);
+
+  *message.mutable_on_composition_canceled() = ime::OnCompositionCanceled();
+
+  return message;
+}
+
 }  // namespace ime
 }  // namespace chromeos
diff --git a/chromeos/services/ime/decoder/proto_conversion.h b/chromeos/services/ime/decoder/proto_conversion.h
index a39b6cc..35fa41fd 100644
--- a/chromeos/services/ime/decoder/proto_conversion.h
+++ b/chromeos/services/ime/decoder/proto_conversion.h
@@ -14,7 +14,8 @@
 namespace ime {
 
 // Converts arguments of a Mojo call to InputChannel::OnFocus into a proto.
-ime::PublicMessage OnFocusToProto(uint64_t seq_id);
+ime::PublicMessage OnFocusToProto(uint64_t seq_id,
+                                  mojom::InputFieldInfoPtr input_field_info);
 
 // Converts arguments of a Mojo call to InputChannel::OnBlur into a proto.
 ime::PublicMessage OnBlurToProto(uint64_t seq_id);
@@ -31,6 +32,10 @@
     uint32_t focus,
     mojom::SelectionRangePtr selection_range);
 
+// Converts arguments of a Mojo call to InputChannel::OnCompositionCanceled into
+// a proto.
+ime::PublicMessage OnCompositionCanceledToProto(uint64_t seq_id);
+
 }  // namespace ime
 }  // namespace chromeos
 
diff --git a/chromeos/services/ime/decoder/proto_conversion_unittest.cc b/chromeos/services/ime/decoder/proto_conversion_unittest.cc
index 48cdefb..fca998b0 100644
--- a/chromeos/services/ime/decoder/proto_conversion_unittest.cc
+++ b/chromeos/services/ime/decoder/proto_conversion_unittest.cc
@@ -11,11 +11,21 @@
 namespace ime {
 
 TEST(ProtoConversionTest, OnFocusToProto) {
+  auto info = mojom::InputFieldInfo::New(mojom::InputFieldType::kNumber,
+                                         mojom::AutocorrectMode::kEnabled,
+                                         mojom::PersonalizationMode::kEnabled);
+
   ime::PublicMessage expected_message;
   expected_message.set_seq_id(42);
-  *expected_message.mutable_on_focus() = ime::OnFocus();
+  ime::OnFocus& args = *expected_message.mutable_on_focus();
+  args.mutable_info()->set_type(ime::InputFieldInfo::INPUT_FIELD_TYPE_NUMBER);
+  args.mutable_info()->set_autocorrect(
+      ime::InputFieldInfo::AUTOCORRECT_MODE_ENABLED);
+  args.mutable_info()->set_personalization(
+      ime::InputFieldInfo::PERSONALIZATION_MODE_ENABLED);
 
-  ime::PublicMessage actual_message = OnFocusToProto(/*seq_id=*/42);
+  ime::PublicMessage actual_message =
+      OnFocusToProto(/*seq_id=*/42, info.Clone());
 
   EXPECT_EQ(actual_message.SerializeAsString(),
             expected_message.SerializeAsString());
@@ -80,5 +90,18 @@
             expected_message.SerializeAsString());
 }
 
+TEST(ProtoConversionTest, OnCompositionCanceledToProto) {
+  ime::PublicMessage expected_message;
+  expected_message.set_seq_id(42);
+  *expected_message.mutable_on_composition_canceled() =
+      ime::OnCompositionCanceled();
+
+  ime::PublicMessage actual_message =
+      OnCompositionCanceledToProto(/*seq_id=*/42);
+
+  EXPECT_EQ(actual_message.SerializeAsString(),
+            expected_message.SerializeAsString());
+}
+
 }  // namespace ime
 }  // namespace chromeos
diff --git a/chromeos/services/ime/ime_service_unittest.cc b/chromeos/services/ime/ime_service_unittest.cc
index d2e2506..ec15abb 100644
--- a/chromeos/services/ime/ime_service_unittest.cc
+++ b/chromeos/services/ime/ime_service_unittest.cc
@@ -55,7 +55,7 @@
   MOCK_METHOD2(ProcessMessage,
                void(const std::vector<uint8_t>& message,
                     ProcessMessageCallback));
-  MOCK_METHOD0(OnFocus, void());
+  MOCK_METHOD1(OnFocus, void(mojom::InputFieldInfoPtr input_field_info));
   MOCK_METHOD0(OnBlur, void());
   MOCK_METHOD2(ProcessKeypressForRulebased,
                void(const mojom::PhysicalKeyEventPtr event,
@@ -67,6 +67,7 @@
                void(const std::string& text,
                     uint32_t offset,
                     mojom::SelectionRangePtr selection_range));
+  MOCK_METHOD0(OnCompositionCanceled, void());
   MOCK_METHOD0(ResetForRulebased, void());
   MOCK_METHOD1(GetRulebasedKeypressCountForTesting,
                void(GetRulebasedKeypressCountForTestingCallback));
diff --git a/chromeos/services/ime/input_engine.cc b/chromeos/services/ime/input_engine.cc
index b3958a1..0cdfcc7 100644
--- a/chromeos/services/ime/input_engine.cc
+++ b/chromeos/services/ime/input_engine.cc
@@ -107,7 +107,7 @@
   NOTIMPLEMENTED();  // Protobuf message is not used in the rulebased engine.
 }
 
-void InputEngine::OnFocus() {
+void InputEngine::OnFocus(mojom::InputFieldInfoPtr input_field_info) {
   NOTIMPLEMENTED();  // Not used in the rulebased engine.
 }
 
@@ -122,6 +122,10 @@
   NOTIMPLEMENTED();  // Not used in the rulebased engine.
 }
 
+void InputEngine::OnCompositionCanceled() {
+  NOTIMPLEMENTED();  // Not used in the rulebased engine.
+}
+
 void InputEngine::ProcessKeypressForRulebased(
     mojom::PhysicalKeyEventPtr event,
     ProcessKeypressForRulebasedCallback callback) {
diff --git a/chromeos/services/ime/input_engine.h b/chromeos/services/ime/input_engine.h
index e1608611..3f8befa 100644
--- a/chromeos/services/ime/input_engine.h
+++ b/chromeos/services/ime/input_engine.h
@@ -46,12 +46,13 @@
   // mojom::InputChannel overrides:
   void ProcessMessage(const std::vector<uint8_t>& message,
                       ProcessMessageCallback callback) override;
-  void OnFocus() override;
+  void OnFocus(mojom::InputFieldInfoPtr input_field_info) override;
   void OnBlur() override;
   void OnSurroundingTextChanged(
       const std::string& text,
       uint32_t offset,
       mojom::SelectionRangePtr selection_range) override;
+  void OnCompositionCanceled() override;
   void ProcessKeypressForRulebased(
       mojom::PhysicalKeyEventPtr event,
       ProcessKeypressForRulebasedCallback callback) override;
diff --git a/chromeos/services/ime/public/mojom/input_engine.mojom b/chromeos/services/ime/public/mojom/input_engine.mojom
index 78e27e33..05ba81c 100644
--- a/chromeos/services/ime/public/mojom/input_engine.mojom
+++ b/chromeos/services/ime/public/mojom/input_engine.mojom
@@ -92,6 +92,48 @@
    uint32 focus;
 };
 
+// Type of input field.
+// Based off ui::TextInputType in ui/base/ime/text_input_type.h.
+enum InputFieldType {
+  // Does not support IME editing. IMEs should only send physical key events,
+  // and not perform complex operations such as composition.
+  kNoIME = 0,
+  // Supports general text input.
+  kText = 1,
+  kSearch = 2,
+  kTelephone = 3,
+  kURL = 4,
+  kEmail = 5,
+  kNumber = 6,
+  // Input represents a password. IMEs should ensure the password is not stored
+  // without the user's permission.
+  kPassword = 7,
+};
+
+enum AutocorrectMode {
+  // The IME must not perform autocorrect.
+  kDisabled = 0,
+  // The IME may perform autocorrect as the user is typing.
+  kEnabled = 1,
+};
+
+enum PersonalizationMode {
+  // The IME should not use anything from the input field to update any
+  // personalized data (e.g. to improve suggestions quality). Personalization
+  // may be disabled if the content is privacy-sensitive (e.g. incognito mode in
+  // Chrome browser), or if using personalization does not make sense (e.g.
+  // playing a typing game may pollute the IME dictionary with uncommon words).
+  kDisabled = 0,
+  // The IME may use the input field contents for personalization.
+  kEnabled = 1,
+};
+
+struct InputFieldInfo {
+  InputFieldType type;
+  AutocorrectMode autocorrect;
+  PersonalizationMode personalization;
+};
+
 // Manages access to a set of IME engines, implemented by the IME service
 // itself. The IME framework in the browser process is responsible for brokering
 // the connection between the IME service and the IME extension, but does not
@@ -123,7 +165,7 @@
   ProcessMessage(array<uint8> message) => (array<uint8> result);
 
   // Called when there's a new focused input field.
-  OnFocus();
+  OnFocus(InputFieldInfo input_field_info);
 
   // Called when the input field loses focus.
   OnBlur();
@@ -143,6 +185,10 @@
                            uint32 offset,
                            SelectionRange selection_range);
 
+  // Informs the IME that composition was canceled by the system. This can
+  // for example happen if the user presses the Escape key.
+  OnCompositionCanceled();
+
   // Process a PhysicalKeyEvent using the rule-based engine and return a
   // KeypressResponseForRulebased object with a list of operations to be handled
   // by the caller.
diff --git a/chromeos/services/ime/public/proto/messages.proto b/chromeos/services/ime/public/proto/messages.proto
index 03959d5..d1f51bd 100644
--- a/chromeos/services/ime/public/proto/messages.proto
+++ b/chromeos/services/ime/public/proto/messages.proto
@@ -34,13 +34,46 @@
     OnKeyEventReply on_key_event_reply = 4;
     OnSurroundingTextChanged on_surrounding_text_changed = 5;
     OnBlur on_blur = 6;
+    OnCompositionCanceled on_composition_canceled = 7;
   }
 }
 
+// Protobuf version of the reply from InputEngine::InputFieldInfo in
+// chromeos/services/ime/public/mojom/input_engine.mojom
+message InputFieldInfo {
+  enum InputFieldType {
+    INPUT_FIELD_TYPE_UNSPECIFIED = 0;  // Reserved
+    INPUT_FIELD_TYPE_NO_IME = 1;
+    INPUT_FIELD_TYPE_TEXT = 2;
+    INPUT_FIELD_TYPE_SEARCH = 3;
+    INPUT_FIELD_TYPE_TELEPHONE = 4;
+    INPUT_FIELD_TYPE_URL = 5;
+    INPUT_FIELD_TYPE_EMAIL = 6;
+    INPUT_FIELD_TYPE_NUMBER = 7;
+    INPUT_FIELD_TYPE_PASSWORD = 8;
+  }
+
+  enum AutocorrectMode {
+    AUTOCORRECT_MODE_UNSPECIFIED = 0;  // Reserved
+    AUTOCORRECT_MODE_DISABLED = 1;
+    AUTOCORRECT_MODE_ENABLED = 2;
+  }
+
+  enum PersonalizationMode {
+    PERSONALIZATION_MODE_UNSPECIFIED = 0;  // Reserved
+    PERSONALIZATION_MODE_DISABLED = 1;
+    PERSONALIZATION_MODE_ENABLED = 2;
+  }
+
+  optional InputFieldType type = 1;
+  optional AutocorrectMode autocorrect = 2;
+  optional PersonalizationMode personalization = 3;
+}
+
 // Protobuf version of InputEngine::OnFocus in
 // chromeos/services/ime/public/mojom/input_engine.mojom
 message OnFocus {
-  // TODO(crbug/1019541): Add information about the input field.
+  optional InputFieldInfo info = 1;
 }
 
 // Protobuf version of InputEngine::OnBlur in
@@ -99,3 +132,7 @@
   optional uint32 offset = 2;
   optional SelectionRange selection_range = 3;
 }
+
+// Protobuf version of InputEngine::OnCompositionCanceled in
+// chromeos/services/ime/public/mojom/input_engine.mojom
+message OnCompositionCanceled {}
diff --git a/components/performance_manager/BUILD.gn b/components/performance_manager/BUILD.gn
index 62166ef..b2e1721 100644
--- a/components/performance_manager/BUILD.gn
+++ b/components/performance_manager/BUILD.gn
@@ -123,6 +123,7 @@
     "public/render_process_host_id.h",
     "public/render_process_host_proxy.h",
     "public/v8_memory/v8_detailed_memory.h",
+    "public/v8_memory/web_memory.h",
     "public/web_contents_proxy.h",
     "registered_objects.h",
     "render_frame_host_proxy.cc",
@@ -144,6 +145,8 @@
     "v8_memory/v8_context_tracker_types.cc",
     "v8_memory/v8_context_tracker_types.h",
     "v8_memory/v8_detailed_memory.cc",
+    "v8_memory/web_memory_aggregator.cc",
+    "v8_memory/web_memory_aggregator.h",
     "web_contents_proxy.cc",
     "web_contents_proxy_impl.cc",
     "web_contents_proxy_impl.h",
@@ -239,6 +242,7 @@
     "v8_memory/v8_context_tracker_internal_unittest.cc",
     "v8_memory/v8_context_tracker_unittest.cc",
     "v8_memory/v8_detailed_memory_unittest.cc",
+    "v8_memory/web_memory_aggregator_unittest.cc",
     "web_contents_proxy_unittest.cc",
     "worker_watcher_unittest.cc",
   ]
diff --git a/components/performance_manager/DEPS b/components/performance_manager/DEPS
index cf77bb8..ae079ef1 100644
--- a/components/performance_manager/DEPS
+++ b/components/performance_manager/DEPS
@@ -8,6 +8,7 @@
   "+net/test",
   "+services/metrics/public/cpp",
   "+services/service_manager/public/cpp",
+  "+third_party/blink/public/common/features.h",
   "+third_party/blink/public/common/tokens",
   "+third_party/blink/public/mojom/favicon",
   "+third_party/blink/public/mojom/performance_manager",
diff --git a/components/performance_manager/graph/frame_node_impl.cc b/components/performance_manager/graph/frame_node_impl.cc
index 2a6c130a..f286d121 100644
--- a/components/performance_manager/graph/frame_node_impl.cc
+++ b/components/performance_manager/graph/frame_node_impl.cc
@@ -12,6 +12,8 @@
 #include "components/performance_manager/graph/process_node_impl.h"
 #include "components/performance_manager/graph/worker_node_impl.h"
 #include "components/performance_manager/public/execution_context_priority/execution_context_priority.h"
+#include "components/performance_manager/public/v8_memory/web_memory.h"
+#include "third_party/blink/public/common/features.h"
 
 namespace performance_manager {
 
@@ -698,4 +700,12 @@
   had_form_interaction.SetAndMaybeNotify(frame_node, false);
 }
 
+void FrameNodeImpl::OnWebMemoryMeasurementRequested(
+    mojom::WebMemoryMeasurement::Mode mode,
+    OnWebMemoryMeasurementRequestedCallback callback) {
+  CHECK(base::FeatureList::IsEnabled(
+      blink::features::kWebMeasureMemoryViaPerformanceManager));
+  v8_memory::WebMeasureMemory(this, mode, std::move(callback));
+}
+
 }  // namespace performance_manager
diff --git a/components/performance_manager/graph/frame_node_impl.h b/components/performance_manager/graph/frame_node_impl.h
index 0ff4a2d..198fb1ee 100644
--- a/components/performance_manager/graph/frame_node_impl.h
+++ b/components/performance_manager/graph/frame_node_impl.h
@@ -15,6 +15,8 @@
 #include "components/performance_manager/graph/node_base.h"
 #include "components/performance_manager/public/graph/frame_node.h"
 #include "components/performance_manager/public/graph/node_attached_data.h"
+#include "components/performance_manager/public/mojom/coordination_unit.mojom.h"
+#include "components/performance_manager/public/mojom/web_memory.mojom.h"
 #include "components/performance_manager/public/render_frame_host_proxy.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
@@ -92,6 +94,9 @@
   void OnFirstContentfulPaint(
       base::TimeDelta time_since_navigation_start) override;
   const RenderFrameHostProxy& GetRenderFrameHostProxy() const override;
+  void OnWebMemoryMeasurementRequested(
+      mojom::WebMemoryMeasurement::Mode mode,
+      OnWebMemoryMeasurementRequestedCallback callback) override;
 
   // Partial FrameNodbase::TimeDelta time_since_navigatione implementation:
   bool IsMainFrame() const override;
diff --git a/components/performance_manager/public/mojom/BUILD.gn b/components/performance_manager/public/mojom/BUILD.gn
index 5ed1eb9..0b5ad814 100644
--- a/components/performance_manager/public/mojom/BUILD.gn
+++ b/components/performance_manager/public/mojom/BUILD.gn
@@ -13,6 +13,7 @@
   sources = [
     "coordination_unit.mojom",
     "lifecycle.mojom",
+    "web_memory.mojom",
   ]
 
   public_deps = [
diff --git a/components/performance_manager/public/mojom/coordination_unit.mojom b/components/performance_manager/public/mojom/coordination_unit.mojom
index 6d845dd9..fbdcbb0 100644
--- a/components/performance_manager/public/mojom/coordination_unit.mojom
+++ b/components/performance_manager/public/mojom/coordination_unit.mojom
@@ -7,6 +7,7 @@
 import "mojo/public/mojom/base/process_id.mojom";
 import "mojo/public/mojom/base/time.mojom";
 import "components/performance_manager/public/mojom/lifecycle.mojom";
+import "components/performance_manager/public/mojom/web_memory.mojom";
 import "ui/gfx/geometry/mojom/geometry.mojom";
 
 // Any new type here needs to be mirrored between coordination_unit_types.h and
@@ -68,6 +69,11 @@
   // or if the content is even visible. It will fire at most once for a given
   // frame. It will only fire for main-frame nodes.
   OnFirstContentfulPaint(mojo_base.mojom.TimeDelta time_since_navigation_start);
+
+  // Invoked when JS in the renderer requests a memory measurement via
+  // the performance.measureMemory API.
+  OnWebMemoryMeasurementRequested(WebMemoryMeasurement.Mode mode) =>
+      (WebMemoryMeasurement measurement);
 };
 
 interface ProcessCoordinationUnit {
diff --git a/components/performance_manager/public/mojom/web_memory.mojom b/components/performance_manager/public/mojom/web_memory.mojom
new file mode 100644
index 0000000..0a753be2
--- /dev/null
+++ b/components/performance_manager/public/mojom/web_memory.mojom
@@ -0,0 +1,65 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module performance_manager.mojom;
+
+// All WebMemory* structs below are used for reporting the memory usage of the
+// page via the performance.measureMemory Web API. These structs roughly follow
+// the structs defined by the specification of the API:
+// https://wicg.github.io/performance-measure-memory/
+//
+// The renderer process invokes the OnWebMemoryMeasurementRequested method of
+// DocumentCoordinationUnit from coordination_unit.mojom to send a memory
+// measurement request to the browser process. The result of the measurement
+// is provided in WebMemoryMeasurement, which attributes the memory usage of
+// the page to ExecutionContexts (iframes and workers).
+//
+// The main invariant is that only the following ExecutionContexts can ever
+// appear in the result:
+// - same-origin contexts, i.e. those that have the same origin as the context
+//   that called the MeasureMemory function.
+// - cross-origin contexts with same-origin parent contexts, i.e. iframes that
+//   are *immediately* embedded in a same-origin context.
+//
+// The invariant is important to ensure that cross-origin contexts embedded
+// in other cross-origin contexts are not observable to the calling origin.
+
+// Information about ExecutionContext reported in the memory usage breakdown.
+struct WebMemoryAttribution {
+  // Specifies the scope (or type) of the context.
+  // The invariant mentioned above ensures that cross-origin contexts have
+  // type kWindow corresponding to iframes and that information is already
+  // known to the calling origin because it created the iframe.
+  enum Scope {
+    kWindow,
+    // TODO(1085129): Add worker scopes once they are implemented.
+  };
+  Scope scope;
+  // The current URL of the context. It is null for cross-origin contexts.
+  string? url;
+
+  // TODO(1085129): Add src and id fields once they are implemented.
+};
+
+// Describes a memory region and attributes it to a set of contexts.
+// Usually the set consists of a single context. If there are multiple
+// contexts then this means that the memory may be owned by any of them.
+struct WebMemoryBreakdownEntry {
+  uint64 bytes;
+  array<WebMemoryAttribution> attribution;
+
+  // TODO(1085129): Add memory types once they are implemented.
+};
+
+// The result of the MeasureMemory function.
+struct WebMemoryMeasurement {
+  // By default a memory measurement may be performed after some delay because
+  // it is folded into the next garbage collection. The eager mode is used for
+  // testing to force the measurement right away.
+  enum Mode {
+    kDefault,
+    kEager
+  };
+  array<WebMemoryBreakdownEntry> breakdown;
+};
diff --git a/components/performance_manager/public/v8_memory/v8_detailed_memory.h b/components/performance_manager/public/v8_memory/v8_detailed_memory.h
index 4740fb3..e748906 100644
--- a/components/performance_manager/public/v8_memory/v8_detailed_memory.h
+++ b/components/performance_manager/public/v8_memory/v8_detailed_memory.h
@@ -292,6 +292,10 @@
   static const V8DetailedMemoryFrameData* ForFrameNode(const FrameNode* node);
 
  private:
+  friend class WebMemoryAggregatorTest;
+  // Creates frame data for the given node.
+  static V8DetailedMemoryFrameData* CreateForTesting(const FrameNode* node);
+
   uint64_t v8_bytes_used_ = 0;
 };
 
diff --git a/components/performance_manager/public/v8_memory/web_memory.h b/components/performance_manager/public/v8_memory/web_memory.h
new file mode 100644
index 0000000..ddf5463
--- /dev/null
+++ b/components/performance_manager/public/v8_memory/web_memory.h
@@ -0,0 +1,33 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_V8_MEMORY_WEB_MEMORY_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_V8_MEMORY_WEB_MEMORY_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/util/type_safety/pass_key.h"
+#include "components/performance_manager/public/mojom/web_memory.mojom.h"
+#include "third_party/blink/public/common/tokens/tokens.h"
+
+namespace performance_manager {
+
+class FrameNode;
+
+namespace v8_memory {
+
+// Implements mojom::DocumentCoordinationUnit::OnWebMemoryMeasurementRequest.
+// Measures memory usage of each frame in the browsing context group of the
+// given frame and invokes the given callback with the result.
+void WebMeasureMemory(const FrameNode*,
+                      mojom::WebMemoryMeasurement::Mode,
+                      base::OnceCallback<void(mojom::WebMemoryMeasurementPtr)>);
+
+}  // namespace v8_memory
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_V8_MEMORY_WEB_MEMORY_H_
diff --git a/components/performance_manager/v8_memory/v8_detailed_memory.cc b/components/performance_manager/v8_memory/v8_detailed_memory.cc
index 701cdc6..c093e0d 100644
--- a/components/performance_manager/v8_memory/v8_detailed_memory.cc
+++ b/components/performance_manager/v8_memory/v8_detailed_memory.cc
@@ -195,6 +195,7 @@
 
  private:
   friend class NodeAttachedProcessData;
+  friend class performance_manager::v8_memory::V8DetailedMemoryFrameData;
 
   V8DetailedMemoryFrameData data_;
   bool data_available_ = false;
@@ -387,9 +388,6 @@
       mojo_mode = blink::mojom::V8DetailedMemoryReporter::Mode::DEFAULT;
       break;
     case MeasurementMode::kEagerForTesting:
-#if DCHECK_IS_ON()
-      DCHECK(g_test_eager_measurement_requests_enabled);
-#endif
       mojo_mode = blink::mojom::V8DetailedMemoryReporter::Mode::EAGER;
       break;
   }
@@ -612,10 +610,6 @@
     : min_time_between_requests_(base::TimeDelta()), mode_(mode) {
   // Do not forward to the standard constructor because it disallows the empty
   // TimeDelta.
-#if DCHECK_IS_ON()
-  DCHECK(mode != MeasurementMode::kEagerForTesting ||
-         g_test_eager_measurement_requests_enabled);
-#endif
 }
 
 V8DetailedMemoryRequest::~V8DetailedMemoryRequest() {
@@ -826,6 +820,13 @@
   return node_data ? node_data->data() : nullptr;
 }
 
+V8DetailedMemoryFrameData* V8DetailedMemoryFrameData::CreateForTesting(
+    const FrameNode* node) {
+  auto* node_data = NodeAttachedFrameData::GetOrCreate(node);
+  node_data->data_available_ = true;
+  return &node_data->data_;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // V8DetailedMemoryProcessData
 
diff --git a/components/performance_manager/v8_memory/v8_detailed_memory_unittest.cc b/components/performance_manager/v8_memory/v8_detailed_memory_unittest.cc
index 59bf58a..1e30ac3f 100644
--- a/components/performance_manager/v8_memory/v8_detailed_memory_unittest.cc
+++ b/components/performance_manager/v8_memory/v8_detailed_memory_unittest.cc
@@ -22,6 +22,7 @@
 #include "components/performance_manager/public/performance_manager.h"
 #include "components/performance_manager/public/render_process_host_id.h"
 #include "components/performance_manager/public/render_process_host_proxy.h"
+#include "components/performance_manager/public/v8_memory/web_memory.h"
 #include "components/performance_manager/test_support/graph_test_harness.h"
 #include "components/performance_manager/test_support/performance_manager_test_harness.h"
 #include "content/public/browser/global_routing_id.h"
@@ -1929,6 +1930,59 @@
   task_environment()->RunUntilIdle();
 }
 
+// TODO(1085129): Move this test to web_memory_aggregator_unittest.cc
+// after extracting the testing infrastructure.
+TEST_F(V8DetailedMemoryRequestAnySeqTest, WebMeasureMemory) {
+  content::IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess());
+  SetContents(CreateTestWebContents());
+
+  // Create a page with a single frame.
+  content::RenderFrameHost* main_frame =
+      content::NavigationSimulator::NavigateAndCommitFromBrowser(
+          web_contents(), GURL("http://foo.com/"));
+  const RenderProcessHostId process_id(main_frame->GetProcess()->GetID());
+
+  blink::LocalFrameToken frame_token =
+      blink::LocalFrameToken(main_frame->GetFrameToken());
+
+  // Call WebMemory::Measure on the performance manager sequence and verify
+  // that the result matches the data provided by the mock reporter.
+  base::WeakPtr<FrameNode> frame_node_wrapper =
+      PerformanceManager::GetFrameNodeForRenderFrameHost(main_frame);
+  bool measurement_done = false;
+  PerformanceManager::CallOnGraph(
+      FROM_HERE,
+      base::BindLambdaForTesting([&frame_node_wrapper, &measurement_done]() {
+        ASSERT_TRUE(frame_node_wrapper);
+        FrameNode* frame_node = frame_node_wrapper.get();
+        WebMeasureMemory(
+            frame_node, mojom::WebMemoryMeasurement::Mode::kDefault,
+            base::BindLambdaForTesting(
+                [&measurement_done](mojom::WebMemoryMeasurementPtr result) {
+                  EXPECT_EQ(1u, result->breakdown.size());
+                  const auto& entry = result->breakdown[0];
+                  EXPECT_EQ(1u, entry->attribution.size());
+                  EXPECT_EQ("http://foo.com/", *(entry->attribution[0]->url));
+                  EXPECT_EQ(1001u, entry->bytes);
+                  measurement_done = true;
+                }));
+      }));
+
+  // Set up and bind the mock reporter.
+  MockV8DetailedMemoryReporter mock_reporter;
+  {
+    auto data = NewPerProcessV8MemoryUsage(1);
+    AddIsolateMemoryUsage(frame_token, 1001u, data->isolates[0].get());
+    ExpectBindAndRespondToQuery(&mock_reporter, std::move(data), process_id);
+  }
+
+  // Finally, run all tasks and verify that the memory measurement callback
+  // was actually invoked.
+  task_environment()->RunUntilIdle();
+  Mock::VerifyAndClearExpectations(&mock_reporter);
+  EXPECT_TRUE(measurement_done);
+}
+
 }  // namespace v8_memory
 
 }  // namespace performance_manager
diff --git a/components/performance_manager/v8_memory/web_memory_aggregator.cc b/components/performance_manager/v8_memory/web_memory_aggregator.cc
new file mode 100644
index 0000000..4447db35
--- /dev/null
+++ b/components/performance_manager/v8_memory/web_memory_aggregator.cc
@@ -0,0 +1,125 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/performance_manager/v8_memory/web_memory_aggregator.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "components/performance_manager/public/graph/frame_node.h"
+#include "components/performance_manager/public/graph/process_node.h"
+#include "components/performance_manager/public/v8_memory/v8_detailed_memory.h"
+#include "components/performance_manager/public/v8_memory/web_memory.h"
+#include "url/gurl.h"
+
+namespace performance_manager {
+
+namespace v8_memory {
+
+namespace {
+
+mojom::WebMemoryMeasurementPtr BuildMemoryUsageResult(
+    const blink::LocalFrameToken& frame_token,
+    const ProcessNode* process_node) {
+  const auto& frame_nodes = process_node->GetFrameNodes();
+
+  // Find the frame that made the request.
+  const FrameNode* requesting_frame = nullptr;
+  for (auto* frame_node : frame_nodes) {
+    if (frame_node->GetFrameToken() == frame_token) {
+      requesting_frame = frame_node;
+      break;
+    }
+  }
+
+  if (!requesting_frame) {
+    // The frame no longer exists.
+    return mojom::WebMemoryMeasurement::New();
+  }
+
+  auto result = mojom::WebMemoryMeasurement::New();
+
+  for (const FrameNode* frame_node : frame_nodes) {
+    if (frame_node->GetBrowsingInstanceId() !=
+        requesting_frame->GetBrowsingInstanceId()) {
+      continue;
+    }
+    if (frame_node->GetURL().GetOrigin() !=
+        requesting_frame->GetURL().GetOrigin()) {
+      continue;
+    }
+    auto* data = v8_memory::V8DetailedMemoryFrameData::ForFrameNode(frame_node);
+    if (!data) {
+      continue;
+    }
+    auto attribution = mojom::WebMemoryAttribution::New();
+    attribution->url = frame_node->GetURL().spec();
+    attribution->scope = mojom::WebMemoryAttribution::Scope::kWindow;
+    auto entry = mojom::WebMemoryBreakdownEntry::New();
+    entry->bytes = data->v8_bytes_used();
+    entry->attribution.push_back(std::move(attribution));
+    result->breakdown.push_back(std::move(entry));
+  }
+  return result;
+}
+
+v8_memory::V8DetailedMemoryRequest::MeasurementMode
+WebMeasurementModeToRequestMeasurementMode(
+    mojom::WebMemoryMeasurement::Mode mode) {
+  switch (mode) {
+    case mojom::WebMemoryMeasurement::Mode::kDefault:
+      return v8_memory::V8DetailedMemoryRequest::MeasurementMode::kDefault;
+    case mojom::WebMemoryMeasurement::Mode::kEager:
+      return v8_memory::V8DetailedMemoryRequest::MeasurementMode::
+          kEagerForTesting;
+  }
+}
+
+}  // anonymous namespace
+
+// Implements the public function in public/v8_memory/web_memory.h
+void WebMeasureMemory(
+    const FrameNode* frame_node,
+    mojom::WebMemoryMeasurement::Mode mode,
+    base::OnceCallback<void(mojom::WebMemoryMeasurementPtr)> callback) {
+  auto web_memory_aggregator = std::make_unique<WebMemoryAggregator>(
+      frame_node->GetFrameToken(), std::move(callback));
+  // Start memory measurementfor the process of the given frame.
+  auto request = std::make_unique<V8DetailedMemoryRequestOneShot>(
+      frame_node->GetProcessNode(),
+      base::BindOnce(&WebMemoryAggregator::MeasurementComplete,
+                     base::Unretained(web_memory_aggregator.get())),
+      WebMeasurementModeToRequestMeasurementMode(mode));
+  WebMemoryAggregator::MakeSelfOwned(std::move(web_memory_aggregator),
+                                     std::move(request));
+}
+
+WebMemoryAggregator::WebMemoryAggregator(
+    const blink::LocalFrameToken& frame_token,
+    MeasurementCallback callback)
+    : frame_token_(frame_token), callback_(std::move(callback)) {}
+
+WebMemoryAggregator::~WebMemoryAggregator() = default;
+
+void WebMemoryAggregator::MeasurementComplete(
+    const ProcessNode* process_node,
+    const V8DetailedMemoryProcessData*) {
+  std::move(callback_).Run(BuildMemoryUsageResult(frame_token_, process_node));
+  self_reference_.reset();
+}
+
+void WebMemoryAggregator::MakeSelfOwned(
+    std::unique_ptr<WebMemoryAggregator> web_memory_aggregator,
+    std::unique_ptr<V8DetailedMemoryRequestOneShot> request) {
+  // Stash the request to ensure that it lives until the measurement is done.
+  web_memory_aggregator->request_ = std::move(request);
+  // Transfer the ownership to itself to make it self-owned. This reference will
+  // be reset in MeasurementCompleted.
+  web_memory_aggregator->self_reference_ = std::move(web_memory_aggregator);
+}
+
+}  // namespace v8_memory
+
+}  // namespace performance_manager
diff --git a/components/performance_manager/v8_memory/web_memory_aggregator.h b/components/performance_manager/v8_memory/web_memory_aggregator.h
new file mode 100644
index 0000000..71aea45
--- /dev/null
+++ b/components/performance_manager/v8_memory/web_memory_aggregator.h
@@ -0,0 +1,54 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_V8_MEMORY_WEB_MEMORY_AGGREGATOR_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_V8_MEMORY_WEB_MEMORY_AGGREGATOR_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "components/performance_manager/public/mojom/web_memory.mojom.h"
+#include "third_party/blink/public/common/tokens/tokens.h"
+
+namespace performance_manager {
+
+class ProcessNode;
+
+namespace v8_memory {
+
+class V8DetailedMemoryRequestOneShot;
+class V8DetailedMemoryProcessData;
+// A helper class for implementing WebMeasureMemory().
+class WebMemoryAggregator {
+ public:
+  using MeasurementCallback =
+      base::OnceCallback<void(mojom::WebMemoryMeasurementPtr)>;
+
+  WebMemoryAggregator(const blink::LocalFrameToken&, MeasurementCallback);
+
+  ~WebMemoryAggregator();
+
+  // A callback for V8DetailedMemoryRequestOneShot.
+  void MeasurementComplete(const ProcessNode*,
+                           const V8DetailedMemoryProcessData*);
+
+  // Transfer ownership of the given request to the given WebMemoryAggregator
+  // and makes the latter self-owned.
+  static void MakeSelfOwned(std::unique_ptr<WebMemoryAggregator>,
+                            std::unique_ptr<V8DetailedMemoryRequestOneShot>);
+
+ private:
+  blink::LocalFrameToken frame_token_;
+  MeasurementCallback callback_;
+  std::unique_ptr<V8DetailedMemoryRequestOneShot> request_;
+  // WebMemory is self-owned and lives until the measurement request
+  // is completed or failed.
+  std::unique_ptr<WebMemoryAggregator> self_reference_;
+};
+
+}  // namespace v8_memory
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_V8_MEMORY_WEB_MEMORY_AGGREGATOR_H_
diff --git a/components/performance_manager/v8_memory/web_memory_aggregator_unittest.cc b/components/performance_manager/v8_memory/web_memory_aggregator_unittest.cc
new file mode 100644
index 0000000..407e3efd
--- /dev/null
+++ b/components/performance_manager/v8_memory/web_memory_aggregator_unittest.cc
@@ -0,0 +1,146 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/performance_manager/v8_memory/web_memory_aggregator.h"
+
+#include <memory>
+#include <tuple>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/containers/flat_map.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/gtest_util.h"
+#include "base/time/time.h"
+#include "components/performance_manager/graph/frame_node_impl.h"
+#include "components/performance_manager/graph/page_node_impl.h"
+#include "components/performance_manager/graph/process_node_impl.h"
+#include "components/performance_manager/public/performance_manager.h"
+#include "components/performance_manager/public/v8_memory/v8_detailed_memory.h"
+#include "components/performance_manager/public/v8_memory/web_memory.h"
+#include "components/performance_manager/test_support/graph_test_harness.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/tokens/tokens.h"
+#include "url/gurl.h"
+
+namespace performance_manager {
+
+namespace v8_memory {
+
+class WebMemoryAggregatorTest : public GraphTestHarness {
+ public:
+  // Wrapper for the browsing instance id to improve test readability.
+  struct BrowsingInstance {
+    int id;
+  };
+
+  // Wrapper for memory usage bytes to improve test readability.
+  struct Bytes {
+    uint64_t bytes;
+    bool operator==(const Bytes& other) const { return bytes == other.bytes; }
+  };
+
+  void SetUp() override;
+
+  // Creates and adds a new frame node to the graph.
+  FrameNodeImpl* AddFrameNode(std::string url,
+                              BrowsingInstance,
+                              Bytes,
+                              FrameNodeImpl* parent = nullptr);
+
+  // Invokes memory measurement and verifies that the result matches the
+  // expected memory usage that is provided as a table from a frame URL to
+  // bytes.
+  void MeasureAndVerify(FrameNodeImpl* frame,
+                        base::flat_map<std::string, Bytes> expected);
+
+ private:
+  int GetNextUniqueId();
+  TestNodeWrapper<ProcessNodeImpl> process_;
+  TestNodeWrapper<PageNodeImpl> page_;
+  std::vector<TestNodeWrapper<FrameNodeImpl>> frames_;
+  int next_unique_id_ = 0;
+};
+
+void WebMemoryAggregatorTest::SetUp() {
+  process_ = CreateNode<ProcessNodeImpl>();
+  page_ = CreateNode<PageNodeImpl>();
+}
+
+int WebMemoryAggregatorTest::GetNextUniqueId() {
+  return next_unique_id_++;
+}
+
+FrameNodeImpl* WebMemoryAggregatorTest::AddFrameNode(
+    std::string url,
+    BrowsingInstance browsing_instance_id,
+    Bytes memory_usage,
+    FrameNodeImpl* parent) {
+  int frame_tree_node_id = GetNextUniqueId();
+  int frame_routing_id = GetNextUniqueId();
+  auto frame = CreateNode<FrameNodeImpl>(
+      process_.get(), page_.get(), parent, frame_tree_node_id, frame_routing_id,
+      blink::LocalFrameToken(), browsing_instance_id.id);
+  frame->OnNavigationCommitted(GURL(url), /*same document*/ true);
+  V8DetailedMemoryFrameData::CreateForTesting(frame.get())
+      ->set_v8_bytes_used(memory_usage.bytes);
+  frames_.push_back(std::move(frame));
+  return frames_.back().get();
+}
+
+void WebMemoryAggregatorTest::MeasureAndVerify(
+    FrameNodeImpl* frame,
+    base::flat_map<std::string, Bytes> expected) {
+  bool measurement_done = false;
+  WebMemoryAggregator web_memory(
+      frame->frame_token(),
+      base::BindLambdaForTesting([&measurement_done, &expected](
+                                     mojom::WebMemoryMeasurementPtr result) {
+        base::flat_map<std::string, Bytes> actual;
+        for (const auto& entry : result->breakdown) {
+          EXPECT_EQ(1u, entry->attribution.size());
+          EXPECT_EQ(mojom::WebMemoryAttribution::Scope::kWindow,
+                    entry->attribution[0]->scope);
+          actual[*entry->attribution[0]->url] = Bytes{entry->bytes};
+        }
+        EXPECT_EQ(expected, actual);
+        measurement_done = true;
+      }));
+  V8DetailedMemoryProcessData process_data;
+  web_memory.MeasurementComplete(process_.get(), &process_data);
+  EXPECT_TRUE(measurement_done);
+}
+
+TEST_F(WebMemoryAggregatorTest, IncludeSameOriginRelatedFrames) {
+  auto* main = AddFrameNode("http://foo.com/", BrowsingInstance{0}, Bytes{10u});
+
+  AddFrameNode("http://foo.com/iframe", BrowsingInstance{0}, Bytes{20}, main);
+
+  MeasureAndVerify(main, {
+                             {"http://foo.com/", Bytes{10u}},
+                             {"http://foo.com/iframe", Bytes{20u}},
+                         });
+}
+
+TEST_F(WebMemoryAggregatorTest, SkipCrossOriginFrames) {
+  auto* main = AddFrameNode("http://foo.com", BrowsingInstance{0}, Bytes{10u});
+
+  AddFrameNode("http://bar.com/iframe", BrowsingInstance{0}, Bytes{20}, main);
+
+  MeasureAndVerify(main, {{"http://foo.com/", Bytes{10u}}});
+}
+
+TEST_F(WebMemoryAggregatorTest, SkipUnrelatedFrames) {
+  auto* main = AddFrameNode("http://foo.com", BrowsingInstance{0}, Bytes{10u});
+
+  AddFrameNode("http://foo.com/unrelated", BrowsingInstance{1}, Bytes{20});
+
+  MeasureAndVerify(main, {{"http://foo.com/", Bytes{10u}}});
+}
+
+}  // namespace v8_memory
+
+}  // namespace performance_manager
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc
index f3959c7..fb387b64 100644
--- a/components/plugins/renderer/webview_plugin.cc
+++ b/components/plugins/renderer/webview_plugin.cc
@@ -258,13 +258,17 @@
 
 WebViewPlugin::WebViewHelper::WebViewHelper(WebViewPlugin* plugin,
                                             const WebPreferences& preferences)
-    : plugin_(plugin) {
+    : plugin_(plugin),
+      agent_group_scheduler_(
+          blink::scheduler::WebThreadScheduler::MainThreadScheduler()
+              ->CreateAgentGroupScheduler()) {
   web_view_ =
       WebView::Create(/*client=*/this,
                       /*is_hidden=*/false,
                       /*is_inside_portal=*/false,
                       /*compositing_enabled=*/false,
-                      /*opener=*/nullptr, mojo::NullAssociatedReceiver());
+                      /*opener=*/nullptr, mojo::NullAssociatedReceiver(),
+                      *agent_group_scheduler_);
   // ApplyWebPreferences before making a WebLocalFrame so that the frame sees a
   // consistent view of our preferences.
   blink::WebView::ApplyWebPreferences(preferences, web_view_);
diff --git a/components/plugins/renderer/webview_plugin.h b/components/plugins/renderer/webview_plugin.h
index 8fc1b377..6b3f246 100644
--- a/components/plugins/renderer/webview_plugin.h
+++ b/components/plugins/renderer/webview_plugin.h
@@ -15,6 +15,7 @@
 #include "mojo/public/cpp/bindings/associated_remote.h"
 #include "third_party/blink/public/mojom/input/focus_type.mojom-forward.h"
 #include "third_party/blink/public/mojom/page/widget.mojom.h"
+#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url_response.h"
 #include "third_party/blink/public/web/blink.h"
@@ -216,6 +217,9 @@
     WebViewPlugin* plugin_;
     blink::WebNavigationControl* frame_ = nullptr;
 
+    std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+        agent_group_scheduler_;
+
     // Owned by us, deleted via |close()|.
     blink::WebView* web_view_;
 
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index 3830168..2f1fb86 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -46,6 +46,8 @@
 #include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom.h"
 #include "third_party/blink/public/mojom/page/widget.mojom.h"
 #include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/public/platform/web_data.h"
 #include "third_party/blink/public/platform/web_double_size.h"
 #include "third_party/blink/public/platform/web_size.h"
@@ -672,7 +674,7 @@
       /*client=*/nullptr,
       /*is_hidden=*/false, /*is_inside_portal=*/false,
       /*compositing_enabled=*/false, /*opener=*/nullptr,
-      mojo::NullAssociatedReceiver());
+      mojo::NullAssociatedReceiver(), *source_frame.GetAgentGroupScheduler());
   web_view->GetSettings()->SetJavaScriptEnabled(true);
 
   class HeaderAndFooterClient final : public blink::WebLocalFrameClient {
@@ -839,6 +841,7 @@
   const bool should_print_backgrounds_;
   const bool should_print_selection_only_;
   bool is_printing_started_ = false;
+  blink::scheduler::WebAgentGroupScheduler& agent_group_scheduler_;
 
   base::WeakPtrFactory<PrepareFrameAndViewForPrint> weak_ptr_factory_{this};
 };
@@ -852,7 +855,8 @@
       original_frame_(frame),
       node_to_print_(node),
       should_print_backgrounds_(params.should_print_backgrounds),
-      should_print_selection_only_(params.selection_only) {
+      should_print_selection_only_(params.selection_only),
+      agent_group_scheduler_(*frame->GetAgentGroupScheduler()) {
   TRACE_EVENT0("print", "PrepareFrameAndViewForPrint");
 
   mojom::PrintParamsPtr print_params = params.Clone();
@@ -947,7 +951,8 @@
       /*is_hidden=*/false,
       /*is_inside_portal=*/false,
       /*compositing_enabled=*/false,
-      /*opener=*/nullptr, mojo::NullAssociatedReceiver());
+      /*opener=*/nullptr, mojo::NullAssociatedReceiver(),
+      agent_group_scheduler_);
   blink::WebView::ApplyWebPreferences(prefs, web_view);
   blink::WebLocalFrame* main_frame = blink::WebLocalFrame::CreateMainFrame(
       web_view, this, nullptr, base::UnguessableToken::Create(), nullptr);
diff --git a/components/services/app_service/public/mojom/types.mojom b/components/services/app_service/public/mojom/types.mojom
index 7392ec0..b3acba6 100644
--- a/components/services/app_service/public/mojom/types.mojom
+++ b/components/services/app_service/public/mojom/types.mojom
@@ -92,7 +92,7 @@
   kCrostini,   // Linux (via Crostini) app.
   kExtension,  // Extension-backed app.
   kWeb,        // Web app.
-  kMacNative,  // Native Mac app.
+  kMacOs,      // Mac OS app.
   kPluginVm,   // Plugin VM app, see go/pluginvm.
   kLacros,     // Lacros browser app, see //docs/lacros.md.
   kRemote,     // Remote app.
diff --git a/components/viz/service/display/overlay_candidate.cc b/components/viz/service/display/overlay_candidate.cc
index d320f89..925eefbb 100644
--- a/components/viz/service/display/overlay_candidate.cc
+++ b/components/viz/service/display/overlay_candidate.cc
@@ -102,6 +102,22 @@
 
   return false;  // No occluding damges
 }
+
+gfx::Rect GetDamageRect(const SharedQuadState* shared_quad_state,
+                        SurfaceDamageRectList* surface_damage_rect_list) {
+  if (!shared_quad_state->overlay_damage_index.has_value())
+    return gfx::Rect();
+
+  size_t overlay_damage_index = shared_quad_state->overlay_damage_index.value();
+  // Invalid index.
+  if (overlay_damage_index >= surface_damage_rect_list->size()) {
+    DCHECK(false);
+    return gfx::Rect();
+  }
+
+  return (*surface_damage_rect_list)[overlay_damage_index];
+}
+
 }  // namespace
 
 OverlayCandidate::OverlayCandidate()
@@ -116,7 +132,6 @@
       is_backed_by_surface_texture(false),
       is_promotable_hint(false),
 #endif
-      plane_z_order(0),
       is_unoccluded(false),
       overlay_handled(false),
       gpu_fence_id(0) {
@@ -198,8 +213,8 @@
         overlap_iter->shared_quad_state->quad_to_target_transform,
         gfx::RectF(overlap_iter->rect)));
 
-    if (display_rect.Intersects(overlap_rect) &&
-        !OverlayCandidate::IsInvisibleQuad(*overlap_iter)) {
+    if (!OverlayCandidate::IsInvisibleQuad(*overlap_iter) &&
+        display_rect.Intersects(overlap_rect)) {
       return true;
     }
   }
@@ -207,6 +222,36 @@
 }
 
 // static
+int OverlayCandidate::EstimateVisibleDamage(
+    const DrawQuad* quad,
+    SurfaceDamageRectList* surface_damage_rect_list,
+    QuadList::ConstIterator quad_list_begin,
+    QuadList::ConstIterator quad_list_end) {
+  gfx::Rect quad_damage =
+      GetDamageRect(quad->shared_quad_state, surface_damage_rect_list);
+  int occluded_damage_estimate_total = 0;
+  for (auto overlap_iter = quad_list_begin; overlap_iter != quad_list_end;
+       ++overlap_iter) {
+    gfx::Rect overlap_rect = gfx::ToRoundedRect(cc::MathUtil::MapClippedRect(
+        overlap_iter->shared_quad_state->quad_to_target_transform,
+        gfx::RectF(overlap_iter->rect)));
+
+    // Opaque quad that (partially) occludes this candidate.
+    if (!OverlayCandidate::IsInvisibleQuad(*overlap_iter) &&
+        !overlap_iter->ShouldDrawWithBlending()) {
+      overlap_rect.Intersect(quad_damage);
+      occluded_damage_estimate_total += overlap_rect.size().GetArea();
+    }
+  }
+  // In the case of overlapping UI the |occluded_damage_estimate_total| may
+  // exceed the |quad|'s damage rect that is in consideration. This is the
+  // reason why this computation is an estimate and why we have the max clamping
+  // below.
+  return std::max(
+      0, quad_damage.size().GetArea() - occluded_damage_estimate_total);
+}
+
+// static
 bool OverlayCandidate::RequiresOverlay(const DrawQuad* quad) {
   switch (quad->material) {
     case DrawQuad::Material::kTextureContent:
@@ -277,11 +322,17 @@
   candidate->is_opaque = !quad->ShouldDrawWithBlending();
   candidate->no_occluding_damage =
       !HasOccludingDamage(quad->shared_quad_state, surface_damage_rect_list);
-
+  // For underlays the function 'EstimateVisibleDamage()' is called to update
+  // |damage_area_estimate| to more accurately reflect the actual visible
+  // damage.
+  candidate->damage_area_estimate =
+      GetDamageRect(quad->shared_quad_state, surface_damage_rect_list)
+          .size()
+          .GetArea();
   candidate->resource_id = resource_id;
   candidate->transform = overlay_transform;
   candidate->mailbox = resource_provider->GetMailbox(resource_id);
-
+  candidate->requires_overlay = OverlayCandidate::RequiresOverlay(quad);
   return true;
 }
 
@@ -304,7 +355,14 @@
   candidate->transform = overlay_transform;
   candidate->no_occluding_damage =
       !HasOccludingDamage(quad->shared_quad_state, surface_damage_rect_list);
-
+  // For underlays the function 'EstimateVisibleDamage()' is called to update
+  // |damage_area_estimate| to more accurately reflect the actual visible
+  // damage.
+  candidate->damage_area_estimate =
+      GetDamageRect(quad->shared_quad_state, surface_damage_rect_list)
+          .size()
+          .GetArea();
+  candidate->requires_overlay = OverlayCandidate::RequiresOverlay(quad);
   return true;
 }
 
diff --git a/components/viz/service/display/overlay_candidate.h b/components/viz/service/display/overlay_candidate.h
index 99c9a0f..79b10d4 100644
--- a/components/viz/service/display/overlay_candidate.h
+++ b/components/viz/service/display/overlay_candidate.h
@@ -51,6 +51,17 @@
                          QuadList::ConstIterator quad_list_begin,
                          QuadList::ConstIterator quad_list_end);
 
+  // Returns an estimate of this |quad|'s actual visible damage area. This
+  // visible damage is computed by combining from input
+  // |surface_damage_rect_list| with the occluding rects in the quad_list.
+  // This is an estimate since the occluded damage area is calculated on a per
+  // quad basis.
+  static int EstimateVisibleDamage(
+      const DrawQuad* quad,
+      SurfaceDamageRectList* surface_damage_rect_list,
+      QuadList::ConstIterator quad_list_begin,
+      QuadList::ConstIterator quad_list_end);
+
   // Returns true if any of the quads in the list given by |quad_list_begin|
   // and |quad_list_end| have a filter associated and occlude |candidate|.
   static bool IsOccludedByFilteredQuad(
@@ -108,7 +119,8 @@
 
   // Stacking order of the overlay plane relative to the main surface,
   // which is 0. Signed to allow for "underlays".
-  int plane_z_order;
+  int plane_z_order = 0;
+
   // True if the overlay does not have any visible quads on top of it. Set by
   // the strategy so the OverlayProcessor can consider subtracting damage caused
   // by underlay quads.
@@ -121,6 +133,13 @@
   // Gpu fence to wait for before overlay is ready for display.
   unsigned gpu_fence_id;
 
+  // The total area in square pixels of damage for this candidate's quad. This
+  // is an estimate when 'EstimateOccludedDamage' function is used.
+  int damage_area_estimate = 0;
+
+  // Cached result of call to 'RequiresOverlay' function.
+  bool requires_overlay = false;
+
  private:
   static bool FromDrawQuadResource(
       DisplayResourceProvider* resource_provider,
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc
index e92d19e..7f65e55 100644
--- a/components/viz/service/display/overlay_unittest.cc
+++ b/components/viz/service/display/overlay_unittest.cc
@@ -4,6 +4,7 @@
 
 #include <stddef.h>
 
+#include <unordered_map>
 #include <utility>
 #include <vector>
 
@@ -3278,5 +3279,121 @@
       render_pass->quad_list.end()));
 }
 
+TEST_F(SingleOverlayOnTopTest, IsOverlayRequiredBasic) {
+  // Add a small quad.
+  auto pass = CreateRenderPass();
+  const auto kSmallCandidateRect = gfx::Rect(0, 0, 16, 16);
+  auto* new_quad = CreateCandidateQuadAt(
+      resource_provider_.get(), child_resource_provider_.get(),
+      child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(),
+      kSmallCandidateRect);
+  SurfaceDamageRectList surface_damage_rect_list;
+  SkMatrix44 default_color = GetIdentityColorMatrix();
+  OverlayCandidate candidate;
+  OverlayCandidate::FromDrawQuad(resource_provider_.get(),
+                                 &surface_damage_rect_list, default_color,
+                                 new_quad, &candidate);
+
+  // Verify that a default candidate is not a required overlay.
+  EXPECT_FALSE(candidate.requires_overlay);
+
+  ASSERT_EQ(gfx::ToRoundedRect(candidate.display_rect), kSmallCandidateRect);
+}
+
+TEST_F(UnderlayTest, EstimateOccludedDamage) {
+  // A visual depiction of how this test works.
+  //   * - Candidate
+  //   # - Occluder
+  //
+  //   The first candidate has no quad occlusions.
+  ///
+  //   ***********
+  //   *         *
+  //   *         *
+  //   *         *
+  //   ***********
+  //
+  //     The second candidate has only one quad occlusion.
+  //                      ######*****************
+  //                      #    #    *           *
+  //                      ######    *           *
+  //                      *         *           *
+  //                      **********######      *
+  //                      *         #    #      *
+  //                      *         ######      *
+  //                      *                     *
+  //                      *                     *
+  //                      ***********************
+  // Finally the third larger candidate is occluded by both quads.
+  // The |damage_area_estimate| reflects this damage occlusion when
+  // 'EstimateOccludedDamage' is called
+
+  auto pass = CreateRenderPass();
+  gfx::Transform identity;
+  identity.MakeIdentity();
+
+  // These quads will server to occlude some of our test overlay candidates.
+  const int kOccluderWidth = 10;
+  AddQuad(gfx::Rect(100, 100, kOccluderWidth, kOccluderWidth), identity,
+          pass.get());
+  AddQuad(gfx::Rect(150, 150, kOccluderWidth, kOccluderWidth), identity,
+          pass.get());
+
+  const int kCandidateSmallWidth = 50;
+  const int kCandidateLargeWidth = 100;
+  const gfx::Rect kCandidateRects[] = {
+      gfx::Rect(0, 0, kCandidateSmallWidth, kCandidateSmallWidth),
+      gfx::Rect(100, 100, kCandidateSmallWidth, kCandidateSmallWidth),
+      gfx::Rect(100, 100, kCandidateLargeWidth, kCandidateLargeWidth)};
+
+  const int kExpectedDamages[] = {kCandidateSmallWidth * kCandidateSmallWidth,
+                                  kCandidateSmallWidth * kCandidateSmallWidth -
+                                      kOccluderWidth * kOccluderWidth,
+                                  kCandidateLargeWidth * kCandidateLargeWidth -
+                                      kOccluderWidth * kOccluderWidth * 2};
+  QuadList& quad_list = pass->quad_list;
+  auto occluder_iter_count = quad_list.size();
+
+  for (size_t i = 0; i < base::size(kCandidateRects); ++i) {
+    SurfaceDamageRectList surface_damage_rect_list;
+    // Create fake surface damage for this candidate.
+    SharedQuadState* damaged_shared_quad_state =
+        pass->shared_quad_state_list.AllocateAndCopyFrom(
+            pass->shared_quad_state_list.back());
+    damaged_shared_quad_state->overlay_damage_index = 0;
+    surface_damage_rect_list.emplace_back(kCandidateRects[i]);
+
+    auto* quad_candidate = CreateCandidateQuadAt(
+        resource_provider_.get(), child_resource_provider_.get(),
+        child_provider_.get(), damaged_shared_quad_state, pass.get(),
+        kCandidateRects[i]);
+
+    SkMatrix44 default_color = GetIdentityColorMatrix();
+    OverlayCandidate candidate;
+    OverlayCandidate::FromDrawQuad(resource_provider_.get(),
+                                   &surface_damage_rect_list, default_color,
+                                   quad_candidate, &candidate);
+
+    // Before the 'EstimateOccludedDamage' function is called the damage area
+    // will just be whatever comes from the |surface_damage_rect_list|.
+    ASSERT_EQ(kCandidateRects[i].size().GetArea(),
+              candidate.damage_area_estimate);
+
+    // We have to find the occluder end of our list as it changes each
+    // iteration.
+    auto iter_occluder_end = quad_list.begin();
+    for (size_t j = 0; j < occluder_iter_count; j++) {
+      iter_occluder_end++;
+    }
+
+    // Now we test the opaque occlusion provided by 'EstimateOccludedDamage'
+    // function.
+    candidate.damage_area_estimate = OverlayCandidate::EstimateVisibleDamage(
+        quad_candidate, &surface_damage_rect_list, quad_list.begin(),
+        iter_occluder_end);
+    ASSERT_EQ(kExpectedDamages[i], candidate.damage_area_estimate);
+  }
+}
+
 }  // namespace
 }  // namespace viz
diff --git a/content/browser/cross_origin_opener_policy_browsertest.cc b/content/browser/cross_origin_opener_policy_browsertest.cc
index a31fbbae..7f30e95 100644
--- a/content/browser/cross_origin_opener_policy_browsertest.cc
+++ b/content/browser/cross_origin_opener_policy_browsertest.cc
@@ -526,9 +526,6 @@
 
 IN_PROC_BROWSER_TEST_P(CrossOriginOpenerPolicyBrowserTest,
                        CoopPageCrashIntoNonCoop) {
-  // TODO(http://crbug.com/1066376): Remove this when the test case passes.
-  if (ShouldCreateNewHostForCrashedFrame())
-    return;
   IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess());
   GURL non_coop_page(https_server()->GetURL("a.com", "/title1.html"));
   GURL coop_page = https_server()->GetURL(
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc
index 392d859..7bed09d 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -86,6 +86,23 @@
 using indexed_db::PutVarInt;
 using indexed_db::ReportOpenStatus;
 
+// An RAII helper to ensure that "DidCommitTransaction" is called
+// during this class's destruction.
+class AutoDidCommitTransaction {
+ public:
+  explicit AutoDidCommitTransaction(IndexedDBBackingStore* backing_store)
+      : backing_store_(backing_store) {
+    DCHECK(backing_store_);
+  }
+  ~AutoDidCommitTransaction() { backing_store_->DidCommitTransaction(); }
+
+  AutoDidCommitTransaction(const AutoDidCommitTransaction&) = delete;
+  AutoDidCommitTransaction operator=(const AutoDidCommitTransaction&) = delete;
+
+ private:
+  IndexedDBBackingStore* backing_store_;
+};
+
 namespace {
 
 FilePath GetBlobDirectoryName(const FilePath& path_base, int64_t database_id) {
@@ -3151,7 +3168,14 @@
   DCHECK(committing_);
   committing_ = false;
 
-  backing_store_->DidCommitTransaction();
+  // DidCommitTransaction must be called during CommitPhaseTwo,
+  // as it decrements the number of active transactions that were
+  // incremented from CommitPhaseOne.  However, it also potentially cleans up
+  // the recovery blob journal, and so needs to be done after the newly
+  // written blobs have been removed from the recovery journal further below.
+  // As there are early outs in this function, use an RAII helper here.
+  AutoDidCommitTransaction run_did_commit_transaction_on_return(
+      backing_store_.get());
 
   BlobJournalType recovery_journal, active_journal, saved_recovery_journal,
       inactive_blobs;
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h
index db673b0..c0deffe 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -51,6 +51,7 @@
 }  // namespace blink
 
 namespace content {
+class AutoDidCommitTransaction;
 class IndexedDBActiveBlobRegistry;
 class LevelDBWriteBatch;
 class TransactionalLevelDBDatabase;
@@ -501,6 +502,9 @@
     return num_aggregated_journal_cleaning_requests_;
   }
 #endif
+  void SetExecuteJournalCleaningOnNoTransactionsForTesting() {
+    execute_journal_cleaning_on_no_txns_ = true;
+  }
 
   // Stops the journal_cleaning_timer_ and runs its pending task.
   void ForceRunBlobCleanup();
@@ -558,6 +562,8 @@
   void CleanRecoveryJournalIgnoreReturn();
 
  private:
+  friend class AutoDidCommitTransaction;
+
   leveldb::Status FindKeyInIndex(
       IndexedDBBackingStore::Transaction* transaction,
       int64_t database_id,
diff --git a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
index 13dc0ac..badb1c4 100644
--- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -894,6 +894,68 @@
   task_environment_.RunUntilIdle();
 }
 
+// http://crbug.com/1131151
+// Validate that recovery journal cleanup during a transaction does
+// not delete blobs that were just written.
+TEST_P(IndexedDBBackingStoreTestWithExternalObjects, BlobWriteCleanup) {
+  const std::vector<IndexedDBKey> keys = {
+      IndexedDBKey(ASCIIToUTF16("key0")), IndexedDBKey(ASCIIToUTF16("key1")),
+      IndexedDBKey(ASCIIToUTF16("key2")), IndexedDBKey(ASCIIToUTF16("key3"))};
+
+  const int64_t database_id = 1;
+  const int64_t object_store_id = 1;
+
+  external_objects().clear();
+  for (size_t j = 0; j < 4; ++j) {
+    std::string type = "type " + base::NumberToString(j);
+    external_objects().push_back(CreateBlobInfo(base::UTF8ToUTF16(type), 1));
+  }
+
+  std::vector<IndexedDBValue> values = {
+      IndexedDBValue("value0", {external_objects()[0]}),
+      IndexedDBValue("value1", {external_objects()[1]}),
+      IndexedDBValue("value2", {external_objects()[2]}),
+      IndexedDBValue("value3", {external_objects()[3]}),
+  };
+  ASSERT_GE(keys.size(), values.size());
+
+  // Validate that cleaning up after writing blobs does not delete those
+  // blobs.
+  backing_store()->SetExecuteJournalCleaningOnNoTransactionsForTesting();
+
+  std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1 =
+      std::make_unique<IndexedDBBackingStore::Transaction>(
+          backing_store()->AsWeakPtr(),
+          blink::mojom::IDBTransactionDurability::Relaxed,
+          blink::mojom::IDBTransactionMode::ReadWrite);
+  transaction1->Begin(CreateDummyLock());
+  IndexedDBBackingStore::RecordIdentifier record;
+  for (size_t i = 0; i < values.size(); ++i) {
+    EXPECT_TRUE(backing_store()
+                    ->PutRecord(transaction1.get(), database_id,
+                                object_store_id, keys[i], &values[i], &record)
+                    .ok());
+  }
+
+  // Start committing transaction1.
+  bool succeeded = false;
+  EXPECT_TRUE(
+      transaction1->CommitPhaseOne(CreateBlobWriteCallback(&succeeded)).ok());
+  task_environment_.RunUntilIdle();
+  EXPECT_TRUE(CheckBlobWrites());
+
+  // Finish committing transaction1.
+  EXPECT_TRUE(succeeded);
+  EXPECT_TRUE(transaction1->CommitPhaseTwo().ok());
+
+  // Verify lack of blob removals.
+  ASSERT_EQ(0UL, backing_store()->removals().size());
+
+  // Clean up on the IDB sequence.
+  transaction1.reset();
+  task_environment_.RunUntilIdle();
+}
+
 TEST_P(IndexedDBBackingStoreTestWithExternalObjects, DeleteRange) {
   const std::vector<IndexedDBKey> keys = {
       IndexedDBKey(ASCIIToUTF16("key0")), IndexedDBKey(ASCIIToUTF16("key1")),
diff --git a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
index 3ae072a7..5df51bbc 100644
--- a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
+++ b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
@@ -3813,6 +3813,8 @@
   // 5) Let the navigation finish and make sure it is succeeded.
   manager.WaitForNavigationFinished();
   EXPECT_EQ(url_b, web_contents()->GetMainFrame()->GetLastCommittedURL());
+  // The RenderFrameHost has been replaced after the crash, so get it again.
+  current_rfh = root->render_manager()->current_frame_host();
   EXPECT_EQ(LifecycleState::kActive, current_rfh->lifecycle_state());
 }
 
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
index 67b967b6..32d22a7 100644
--- a/content/browser/renderer_host/render_frame_host_manager.cc
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -829,8 +829,6 @@
 
     if (!render_frame_host_->IsRenderFrameLive() &&
         !recovering_without_early_commit) {
-      // We should only do this if the current RFH is not live.
-      DCHECK(!render_frame_host_->IsRenderFrameLive());
       // The current RFH is not live. There's no reason to sit around with a
       // sad tab or a newly created RFH while we wait for the navigation to
       // complete. Just switch to the speculative RFH now and go back to
diff --git a/content/browser/renderer_host/render_frame_host_manager_unittest.cc b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
index 6f7fbbd0..b6071d60 100644
--- a/content/browser/renderer_host/render_frame_host_manager_unittest.cc
+++ b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
@@ -285,11 +285,16 @@
                                        GetRenderDocumentLevelName(level));
   }
 
+  void DisableRenderDocument() {
+    feature_list_.InitAndDisableFeature(features::kRenderDocument);
+  }
+
  private:
   base::test::ScopedFeatureList feature_list_;
 };
 
 TEST_F(RenderDocumentFeatureTest, FeatureDisabled) {
+  DisableRenderDocument();
   EXPECT_FALSE(ShouldCreateNewHostForCrashedFrame());
   EXPECT_FALSE(ShouldCreateNewHostForSameSiteSubframe());
 }
diff --git a/content/browser/service_worker/service_worker_installed_script_loader.cc b/content/browser/service_worker/service_worker_installed_script_loader.cc
index 197733f..cd08dac 100644
--- a/content/browser/service_worker/service_worker_installed_script_loader.cc
+++ b/content/browser/service_worker/service_worker_installed_script_loader.cc
@@ -92,7 +92,7 @@
     case FinishedReason::kCreateDataPipeError:
       net_error = net::ERR_INSUFFICIENT_RESOURCES;
       break;
-    case FinishedReason::kNoHttpInfoError:
+    case FinishedReason::kNoResponseHeadError:
     case FinishedReason::kResponseReaderError:
       net_error = net::ERR_FILE_NOT_FOUND;
       break;
diff --git a/content/browser/service_worker/service_worker_installed_script_reader.cc b/content/browser/service_worker/service_worker_installed_script_reader.cc
index bb723ab..9b01d20 100644
--- a/content/browser/service_worker/service_worker_installed_script_reader.cc
+++ b/content/browser/service_worker/service_worker_installed_script_reader.cc
@@ -112,12 +112,12 @@
   DCHECK(client_);
   TRACE_EVENT0(
       "ServiceWorker",
-      "ServiceWorkerInstalledScriptReader::OnReadResponseInfoComplete");
+      "ServiceWorkerInstalledScriptReader::OnReadResponseHeadComplete");
   if (!response_head) {
     DCHECK_LT(result, 0);
     ServiceWorkerMetrics::CountReadResponseResult(
         ServiceWorkerMetrics::READ_HEADERS_ERROR);
-    CompleteSendIfNeeded(FinishedReason::kNoHttpInfoError);
+    CompleteSendIfNeeded(FinishedReason::kNoResponseHeadError);
     return;
   }
 
diff --git a/content/browser/service_worker/service_worker_installed_script_reader.h b/content/browser/service_worker/service_worker_installed_script_reader.h
index 03f873e4f..cfa47b5f 100644
--- a/content/browser/service_worker/service_worker_installed_script_reader.h
+++ b/content/browser/service_worker/service_worker_installed_script_reader.h
@@ -30,7 +30,7 @@
   enum class FinishedReason {
     kNotFinished = 0,
     kSuccess = 1,
-    kNoHttpInfoError = 2,
+    kNoResponseHeadError = 2,
     kCreateDataPipeError = 3,
     kConnectionError = 4,
     kResponseReaderError = 5,
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender.cc b/content/browser/service_worker/service_worker_installed_scripts_sender.cc
index a5a344d..6a5e8a1f 100644
--- a/content/browser/service_worker/service_worker_installed_scripts_sender.cc
+++ b/content/browser/service_worker/service_worker_installed_scripts_sender.cc
@@ -186,7 +186,8 @@
     case ServiceWorkerInstalledScriptReader::FinishedReason::kSuccess:
       NOTREACHED();
       return;
-    case ServiceWorkerInstalledScriptReader::FinishedReason::kNoHttpInfoError:
+    case ServiceWorkerInstalledScriptReader::FinishedReason::
+        kNoResponseHeadError:
     case ServiceWorkerInstalledScriptReader::FinishedReason::
         kResponseReaderError:
       owner_->SetStartWorkerStatusCode(
diff --git a/content/browser/webui/web_ui_mojo_browsertest.cc b/content/browser/webui/web_ui_mojo_browsertest.cc
index 7af92a0..39ed1a5 100644
--- a/content/browser/webui/web_ui_mojo_browsertest.cc
+++ b/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -404,6 +404,9 @@
   // available.
   EXPECT_TRUE(NavigateToURL(shell(), test_url));
   EXPECT_TRUE(EvalJs(shell(), "isChromeSendAvailable()").ExtractBool());
+  // The RenderFrameHost has been replaced after the crash, so get web_ui again.
+  web_ui = static_cast<WebUIImpl*>(
+      shell()->web_contents()->GetMainFrame()->GetWebUI());
   EXPECT_TRUE(web_ui->GetRemoteForTest().is_bound());
 }
 
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc
index fac5956..8a7d429 100644
--- a/content/child/child_thread_impl.cc
+++ b/content/child/child_thread_impl.cc
@@ -397,8 +397,8 @@
   mojo::Receiver<mojom::ChildProcess> receiver_{this};
 
   // The pending legacy IPC channel endpoint to fuse with one we will eventually
-  // receiver on the ChildProcess interface. Only used when not in the
-  // deprecated Service Manager IPC mode.
+  // receive on the ChildProcess interface. Only used when not in the deprecated
+  // Service Manager IPC mode.
   mojo::PendingRemote<IPC::mojom::ChannelBootstrap> legacy_ipc_bootstrap_;
 
   // Binding requests which should be handled by |interface_binders|, but which
diff --git a/content/common/content_navigation_policy.cc b/content/common/content_navigation_policy.cc
index a5c1e837..faee3f1 100644
--- a/content/common/content_navigation_policy.cc
+++ b/content/common/content_navigation_policy.cc
@@ -140,7 +140,7 @@
         {RenderDocumentLevel::kSubframe, "subframe"}};
 const base::FeatureParam<RenderDocumentLevel> render_document_level{
     &features::kRenderDocument, kRenderDocumentLevelParameterName,
-    RenderDocumentLevel::kDisabled, &render_document_levels};
+    RenderDocumentLevel::kCrashedFrame, &render_document_levels};
 
 RenderDocumentLevel GetRenderDocumentLevel() {
   if (base::FeatureList::IsEnabled(features::kRenderDocument))
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 77b45903..c00ddea7 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -535,7 +535,7 @@
 
 // Enable using the RenderDocument.
 const base::Feature kRenderDocument{"RenderDocument",
-                                    base::FEATURE_DISABLED_BY_DEFAULT};
+                                    base::FEATURE_ENABLED_BY_DEFAULT};
 // Enables skipping the early call to CommitPending when navigating away from a
 // crashed frame.
 const base::Feature kSkipEarlyCommitPendingForCrashedFrame{
diff --git a/content/public/common/navigation_policy.h b/content/public/common/navigation_policy.h
index b69765e..88c0c26 100644
--- a/content/public/common/navigation_policy.h
+++ b/content/public/common/navigation_policy.h
@@ -93,8 +93,8 @@
 CONTENT_EXPORT bool ShouldCreateNewHostForCrashedFrame();
 
 // If this is false we continue the old behaviour of doing an early call to
-// RenderFrameHostManager::CommitPending when we are replacing an inactive
-// frame (crashed or just newly created but never live).
+// RenderFrameHostManager::CommitPending when we are replacing a crashed
+// frame.
 // TODO(https://crbug.com/1072817): Stop allowing this.
 CONTENT_EXPORT bool ShouldSkipEarlyCommitPendingForCrashedFrame();
 
diff --git a/content/public/renderer/render_frame.h b/content/public/renderer/render_frame.h
index 96175d5..7e2d93c 100644
--- a/content/public/renderer/render_frame.h
+++ b/content/public/renderer/render_frame.h
@@ -29,6 +29,9 @@
 #include "ui/accessibility/ax_tree_update.h"
 
 namespace blink {
+namespace scheduler {
+class WebAgentGroupScheduler;
+}  // namespace scheduler
 namespace web_pref {
 struct WebPreferences;
 }  // namespace web_pref
@@ -325,6 +328,11 @@
   // Returns the device scale factor of the display the render frame is in.
   virtual float GetDeviceScaleFactor() = 0;
 
+  // Return the dedicated scheduler for the AgentSchedulingGroup associated with
+  // this RenderFrame.
+  virtual blink::scheduler::WebAgentGroupScheduler&
+  GetAgentGroupScheduler() = 0;
+
  protected:
   ~RenderFrame() override {}
 
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index cf36aa8..6abad92 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -423,9 +423,6 @@
   if (!render_thread_)
     render_thread_ = std::make_unique<MockRenderThread>();
 
-  agent_scheduling_group_ = CreateAgentSchedulingGroup(*render_thread_);
-  render_widget_host_ = CreateRenderWidgetHost();
-
   // Blink needs to be initialized before calling CreateContentRendererClient()
   // because it uses blink internally.
   blink_platform_impl_.Initialize();
@@ -439,6 +436,9 @@
   SetBrowserClientForTesting(content_browser_client_.get());
   SetRendererClientForTesting(content_renderer_client_.get());
 
+  agent_scheduling_group_ = CreateAgentSchedulingGroup(*render_thread_);
+  render_widget_host_ = CreateRenderWidgetHost();
+
 #if defined(OS_WIN)
   // This needs to happen sometime before PlatformInitialize.
   // This isn't actually necessary for most tests: most tests are able to
diff --git a/content/renderer/agent_scheduling_group.cc b/content/renderer/agent_scheduling_group.cc
index 9fe80bec..1bc4ef3 100644
--- a/content/renderer/agent_scheduling_group.cc
+++ b/content/renderer/agent_scheduling_group.cc
@@ -11,6 +11,7 @@
 #include "content/renderer/render_frame_proxy.h"
 #include "content/renderer/render_thread_impl.h"
 #include "content/renderer/render_view_impl.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 
 namespace content {
 
@@ -37,33 +38,41 @@
 // MaybeAssociatedReceiver:
 AgentSchedulingGroup::MaybeAssociatedReceiver::MaybeAssociatedReceiver(
     AgentSchedulingGroup& impl,
-    PendingReceiver<mojom::AgentSchedulingGroup> receiver)
+    PendingReceiver<mojom::AgentSchedulingGroup> receiver,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
     : receiver_(absl::in_place_type<Receiver<mojom::AgentSchedulingGroup>>,
                 &impl,
-                std::move(receiver)) {}
+                std::move(receiver),
+                task_runner) {}
 
 AgentSchedulingGroup::MaybeAssociatedReceiver::MaybeAssociatedReceiver(
     AgentSchedulingGroup& impl,
-    PendingAssociatedReceiver<mojom::AgentSchedulingGroup> receiver)
+    PendingAssociatedReceiver<mojom::AgentSchedulingGroup> receiver,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
     : receiver_(
           absl::in_place_type<AssociatedReceiver<mojom::AgentSchedulingGroup>>,
           &impl,
-          std::move(receiver)) {}
+          std::move(receiver),
+          task_runner) {}
 
 AgentSchedulingGroup::MaybeAssociatedReceiver::~MaybeAssociatedReceiver() =
     default;
 
 // MaybeAssociatedRemote:
 AgentSchedulingGroup::MaybeAssociatedRemote::MaybeAssociatedRemote(
-    PendingRemote<mojom::AgentSchedulingGroupHost> host_remote)
+    PendingRemote<mojom::AgentSchedulingGroupHost> host_remote,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
     : remote_(absl::in_place_type<Remote<mojom::AgentSchedulingGroupHost>>,
-              std::move(host_remote)) {}
+              std::move(host_remote),
+              task_runner) {}
 
 AgentSchedulingGroup::MaybeAssociatedRemote::MaybeAssociatedRemote(
-    PendingAssociatedRemote<mojom::AgentSchedulingGroupHost> host_remote)
+    PendingAssociatedRemote<mojom::AgentSchedulingGroupHost> host_remote,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
     : remote_(absl::in_place_type<
                   AssociatedRemote<mojom::AgentSchedulingGroupHost>>,
-              std::move(host_remote)) {}
+              std::move(host_remote),
+              task_runner) {}
 
 AgentSchedulingGroup::MaybeAssociatedRemote::~MaybeAssociatedRemote() = default;
 
@@ -77,11 +86,16 @@
     RenderThread& render_thread,
     PendingRemote<mojom::AgentSchedulingGroupHost> host_remote,
     PendingReceiver<mojom::AgentSchedulingGroup> receiver)
-    // TODO(crbug.com/1111231): Mojo interfaces should be associated with
-    // per-ASG task runners instead of default.
-    : render_thread_(render_thread),
-      receiver_(*this, std::move(receiver)),
-      host_remote_(std::move(host_remote)) {
+    : agent_group_scheduler_(
+          blink::scheduler::WebThreadScheduler::MainThreadScheduler()
+              ->CreateAgentGroupScheduler()),
+      render_thread_(render_thread),
+      receiver_(*this,
+                std::move(receiver),
+                agent_group_scheduler_->DefaultTaskRunner()),
+      host_remote_(std::move(host_remote),
+                   agent_group_scheduler_->DefaultTaskRunner()) {
+  DCHECK(agent_group_scheduler_);
   DCHECK(base::FeatureList::IsEnabled(
       features::kMbiDetachAgentSchedulingGroupFromChannel));
 }
@@ -90,11 +104,16 @@
     RenderThread& render_thread,
     PendingAssociatedRemote<mojom::AgentSchedulingGroupHost> host_remote,
     PendingAssociatedReceiver<mojom::AgentSchedulingGroup> receiver)
-    // TODO(crbug.com/1111231): Mojo interfaces should be associated with
-    // per-ASG task runners instead of default.
-    : render_thread_(render_thread),
-      receiver_(*this, std::move(receiver)),
-      host_remote_(std::move(host_remote)) {
+    : agent_group_scheduler_(
+          blink::scheduler::WebThreadScheduler::MainThreadScheduler()
+              ->CreateAgentGroupScheduler()),
+      render_thread_(render_thread),
+      receiver_(*this,
+                std::move(receiver),
+                agent_group_scheduler_->DefaultTaskRunner()),
+      host_remote_(std::move(host_remote),
+                   agent_group_scheduler_->DefaultTaskRunner()) {
+  DCHECK(agent_group_scheduler_);
   DCHECK(!base::FeatureList::IsEnabled(
       features::kMbiDetachAgentSchedulingGroupFromChannel));
 }
diff --git a/content/renderer/agent_scheduling_group.h b/content/renderer/agent_scheduling_group.h
index d22e19c..fa81f6de 100644
--- a/content/renderer/agent_scheduling_group.h
+++ b/content/renderer/agent_scheduling_group.h
@@ -15,6 +15,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom.h"
+#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
 
 namespace IPC {
 class Listener;
@@ -58,6 +59,10 @@
   // This is virtual only for unit tests.
   virtual mojom::RouteProvider* GetRemoteRouteProvider();
 
+  blink::scheduler::WebAgentGroupScheduler& agent_group_scheduler() {
+    return *agent_group_scheduler_;
+  }
+
  private:
   // `MaybeAssociatedReceiver` and `MaybeAssociatedRemote` are temporary helper
   // classes that allow us to switch between using associated and non-associated
@@ -72,10 +77,12 @@
    public:
     MaybeAssociatedReceiver(
         AgentSchedulingGroup& impl,
-        mojo::PendingReceiver<mojom::AgentSchedulingGroup> receiver);
+        mojo::PendingReceiver<mojom::AgentSchedulingGroup> receiver,
+        scoped_refptr<base::SingleThreadTaskRunner> task_runner);
     MaybeAssociatedReceiver(
         AgentSchedulingGroup& impl,
-        mojo::PendingAssociatedReceiver<mojom::AgentSchedulingGroup> receiver);
+        mojo::PendingAssociatedReceiver<mojom::AgentSchedulingGroup> receiver,
+        scoped_refptr<base::SingleThreadTaskRunner> task_runner);
     ~MaybeAssociatedReceiver();
 
    private:
@@ -87,10 +94,12 @@
   class MaybeAssociatedRemote {
    public:
     explicit MaybeAssociatedRemote(
-        mojo::PendingRemote<mojom::AgentSchedulingGroupHost> host_remote);
+        mojo::PendingRemote<mojom::AgentSchedulingGroupHost> host_remote,
+        scoped_refptr<base::SingleThreadTaskRunner> task_runner);
     explicit MaybeAssociatedRemote(
         mojo::PendingAssociatedRemote<mojom::AgentSchedulingGroupHost>
-            host_remote);
+            host_remote,
+        scoped_refptr<base::SingleThreadTaskRunner> task_runner);
     ~MaybeAssociatedRemote();
     mojom::AgentSchedulingGroupHost* get();
 
@@ -128,6 +137,10 @@
       mojo::PendingAssociatedReceiver<blink::mojom::AssociatedInterface>
           receiver) override;
 
+  // A dedicated scheduler for this AgentSchedulingGroup.
+  std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+      agent_group_scheduler_;
+
   RenderThread& render_thread_;
 
   // Implementation of `mojom::AgentSchedulingGroup`, used for responding to
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 87f91ac..b415183 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -170,6 +170,7 @@
 #include "third_party/blink/public/platform/file_path_conversion.h"
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
 #include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
+#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
 #include "third_party/blink/public/platform/url_conversion.h"
 #include "third_party/blink/public/platform/weak_wrapper_resource_load_info_notifier.h"
 #include "third_party/blink/public/platform/web_data.h"
@@ -6622,6 +6623,11 @@
   web_url_loader_factory_override_for_test_ = std::move(factory);
 }
 
+blink::scheduler::WebAgentGroupScheduler&
+RenderFrameImpl::GetAgentGroupScheduler() {
+  return agent_scheduling_group_.agent_group_scheduler();
+}
+
 gfx::RectF RenderFrameImpl::ElementBoundsInWindow(
     const blink::WebElement& element) {
   blink::WebRect bounding_box_in_window = element.BoundsInViewport();
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 430c1085..329af00 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -115,6 +115,10 @@
 #endif
 
 namespace blink {
+namespace scheduler {
+class WebAgentGroupScheduler;
+}  // namespace scheduler
+
 class WeakWrapperResourceLoadInfoNotifier;
 class WebComputedAXTree;
 class WebContentDecryptionModule;
@@ -824,6 +828,8 @@
   void SetWebURLLoaderFactoryOverrideForTest(
       std::unique_ptr<blink::WebURLLoaderFactoryForTest> factory);
 
+  blink::scheduler::WebAgentGroupScheduler& GetAgentGroupScheduler() override;
+
  protected:
   explicit RenderFrameImpl(CreateParams params);
 
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index cf80667..a4a4505 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -147,7 +147,8 @@
       params->type == mojom::ViewWidgetType::kPortal ? true : false,
       /*compositing_enabled=*/true,
       opener_frame ? opener_frame->View() : nullptr,
-      std::move(params->blink_page_broadcast));
+      std::move(params->blink_page_broadcast),
+      agent_scheduling_group_.agent_group_scheduler());
 
   g_view_map.Get().insert(std::make_pair(GetWebView(), this));
   g_routing_id_view_map.Get().insert(std::make_pair(GetRoutingID(), this));
diff --git a/extensions/renderer/scoped_web_frame.cc b/extensions/renderer/scoped_web_frame.cc
index 410d431..13dc6d03 100644
--- a/extensions/renderer/scoped_web_frame.cc
+++ b/extensions/renderer/scoped_web_frame.cc
@@ -6,6 +6,8 @@
 
 #include "mojo/public/cpp/bindings/associated_remote.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/public/web/web_heap.h"
 #include "third_party/blink/public/web/web_view.h"
 #include "third_party/blink/public/web/web_widget.h"
@@ -13,12 +15,16 @@
 namespace extensions {
 
 ScopedWebFrame::ScopedWebFrame()
-    : view_(blink::WebView::Create(/*client=*/nullptr,
-                                   /*is_hidden=*/false,
-                                   /*is_inside_portal=*/false,
-                                   /*compositing_enabled=*/false,
-                                   /*opener=*/nullptr,
-                                   mojo::NullAssociatedReceiver())),
+    : agent_group_scheduler_(
+          blink::scheduler::WebAgentGroupScheduler::CreateForTesting()),
+      view_(blink::WebView::Create(
+          /*client=*/nullptr,
+          /*is_hidden=*/false,
+          /*is_inside_portal=*/false,
+          /*compositing_enabled=*/false,
+          /*opener=*/nullptr,
+          mojo::NullAssociatedReceiver(),
+          *agent_group_scheduler_)),
       frame_(blink::WebLocalFrame::CreateMainFrame(
           view_,
           &frame_client_,
@@ -29,6 +35,7 @@
 ScopedWebFrame::~ScopedWebFrame() {
   view_->Close();
   blink::WebHeap::CollectAllGarbageForTesting();
+  agent_group_scheduler_ = nullptr;
 }
 
 }  // namespace extensions
diff --git a/extensions/renderer/scoped_web_frame.h b/extensions/renderer/scoped_web_frame.h
index f4f4533..2d3a8536 100644
--- a/extensions/renderer/scoped_web_frame.h
+++ b/extensions/renderer/scoped_web_frame.h
@@ -6,6 +6,7 @@
 #define EXTENSIONS_RENDERER_SCOPED_WEB_FRAME_H_
 
 #include "base/macros.h"
+#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_local_frame_client.h"
 #include "third_party/blink/public/web/web_view.h"
@@ -24,9 +25,11 @@
 private:
  blink::WebLocalFrameClient frame_client_;
 
- // The webview and the frame are kept alive by the ScopedWebFrame
- // because they are not destructed unless ~ScopedWebFrame explicitly
- // closes the WebView.
+ // The `WebAgentGroupScheduler`, webview and the frame are kept alive by
+ // the ScopedWebFrame because they are not destructed unless
+ // ~ScopedWebFrame explicitly closes the WebView.
+ std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+     agent_group_scheduler_;
  blink::WebView* view_;
  blink::WebLocalFrame* frame_;
 
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.cc b/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.cc
index 3282d2b3..bbede3c 100644
--- a/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.cc
+++ b/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.cc
@@ -18,19 +18,22 @@
 
 // The maximum number of times to dump before throttling (to avoid sending
 // thousands of crash dumps).
+
 const int kMaxCrashDumps = 10;
 
 uint32_t LockFlags(gfx::BufferUsage usage) {
   switch (usage) {
     case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
-      return kIOSurfaceLockAvoidSync;
     case gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE:
+      // The AvoidSync call has the property that it will not preserve the
+      // previous contents of the buffer if those contents were written by a
+      // GPU.
+      return kIOSurfaceLockAvoidSync;
+    case gfx::BufferUsage::SCANOUT_VEA_CPU_READ:
       // This constant is used for buffers used by video capture. On macOS,
       // these buffers are only ever written to in the capture process,
-      // directly as IOSurfaces. Once they are sent to other processes, no CPU
-      // writes are performed.
-      // TODO(https://crbug.com/1130101): A more accurate usage constant may be
-      // appropriate.
+      // directly as IOSurfaces.
+      // Once they are sent to other processes, no CPU writes are performed.
       return kIOSurfaceLockReadOnly;
     case gfx::BufferUsage::GPU_READ:
     case gfx::BufferUsage::SCANOUT:
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.cc b/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.cc
index 2d1d14d..5f81862 100644
--- a/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.cc
+++ b/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.cc
@@ -163,6 +163,7 @@
     case gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE:
     case gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE:
     case gfx::BufferUsage::SCANOUT_VDA_WRITE:
+    case gfx::BufferUsage::SCANOUT_VEA_CPU_READ:
     case gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE:
       return false;
   }
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_test_template.h b/gpu/ipc/common/gpu_memory_buffer_impl_test_template.h
index 94d4a6c..3dbae0b1 100644
--- a/gpu/ipc/common/gpu_memory_buffer_impl_test_template.h
+++ b/gpu/ipc/common/gpu_memory_buffer_impl_test_template.h
@@ -99,6 +99,7 @@
         gfx::BufferUsage::SCANOUT_CPU_READ_WRITE,
         gfx::BufferUsage::SCANOUT_VDA_WRITE,
         gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
+        gfx::BufferUsage::SCANOUT_VEA_CPU_READ,
         gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE,
     };
     for (auto usage : usages) {
@@ -140,6 +141,7 @@
         gfx::BufferUsage::SCANOUT_CPU_READ_WRITE,
         gfx::BufferUsage::SCANOUT_VDA_WRITE,
         gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
+        gfx::BufferUsage::SCANOUT_VEA_CPU_READ,
         gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE,
     };
     for (auto usage : usages) {
@@ -317,6 +319,7 @@
         gfx::BufferUsage::SCANOUT_CPU_READ_WRITE,
         gfx::BufferUsage::SCANOUT_VDA_WRITE,
         gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
+        gfx::BufferUsage::SCANOUT_VEA_CPU_READ,
         gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE,
     };
     for (auto usage : usages) {
diff --git a/gpu/ipc/common/gpu_memory_buffer_support.cc b/gpu/ipc/common/gpu_memory_buffer_support.cc
index 504fad4..ceb04abd 100644
--- a/gpu/ipc/common/gpu_memory_buffer_support.cc
+++ b/gpu/ipc/common/gpu_memory_buffer_support.cc
@@ -96,6 +96,7 @@
     case gfx::BufferUsage::SCANOUT_VDA_WRITE:
     case gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE:
     case gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE:
+    case gfx::BufferUsage::SCANOUT_VEA_CPU_READ:
     case gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE:
       return false;
   }
@@ -116,6 +117,7 @@
     case gfx::BufferUsage::SCANOUT_VDA_WRITE:
     case gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE:
     case gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE:
+    case gfx::BufferUsage::SCANOUT_VEA_CPU_READ:
     case gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE:
       return false;
   }
@@ -145,6 +147,7 @@
     case gfx::BufferUsage::SCANOUT_VDA_WRITE:
     case gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE:
     case gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE:
+    case gfx::BufferUsage::SCANOUT_VEA_CPU_READ:
     case gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE:
       return false;
   }
diff --git a/gpu/ipc/host/gpu_memory_buffer_support.cc b/gpu/ipc/host/gpu_memory_buffer_support.cc
index 23000255..a774df7 100644
--- a/gpu/ipc/host/gpu_memory_buffer_support.cc
+++ b/gpu/ipc/host/gpu_memory_buffer_support.cc
@@ -40,6 +40,7 @@
       gfx::BufferUsage::SCANOUT_CPU_READ_WRITE,
       gfx::BufferUsage::SCANOUT_VDA_WRITE,
       gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
+      gfx::BufferUsage::SCANOUT_VEA_CPU_READ,
       gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE,
   };
 
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_test_template.h b/gpu/ipc/service/gpu_memory_buffer_factory_test_template.h
index b9abc433..7c82380 100644
--- a/gpu/ipc/service/gpu_memory_buffer_factory_test_template.h
+++ b/gpu/ipc/service/gpu_memory_buffer_factory_test_template.h
@@ -69,6 +69,7 @@
         gfx::BufferUsage::SCANOUT_CPU_READ_WRITE,
         gfx::BufferUsage::SCANOUT_VDA_WRITE,
         gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
+        gfx::BufferUsage::SCANOUT_VEA_CPU_READ,
         gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE,
     };
     for (auto usage : usages) {
diff --git a/ios/chrome/browser/ui/commands/application_commands.h b/ios/chrome/browser/ui/commands/application_commands.h
index 8e7f9ed6..dd889d0 100644
--- a/ios/chrome/browser/ui/commands/application_commands.h
+++ b/ios/chrome/browser/ui/commands/application_commands.h
@@ -119,16 +119,6 @@
                                      sender:(UserFeedbackSender)sender;
 
 // Shows the Report an Issue UI, presenting from |baseViewController|, using
-// |specificProductData| for additional product data to be sent in the report
-// and UserFeedbackSender::ToolsMenu sender.
-// TODO(crbug.com/1138523): Remove this method after Downstream code stop using
-// it.
-- (void)
-    showReportAnIssueFromViewController:(UIViewController*)baseViewController
-                    specificProductData:(NSDictionary<NSString*, NSString*>*)
-                                            specificProductData;
-
-// Shows the Report an Issue UI, presenting from |baseViewController|, using
 // |specificProductData| for additional product data to be sent in the report.
 - (void)
     showReportAnIssueFromViewController:(UIViewController*)baseViewController
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm
index d29aaca..a699019 100644
--- a/ios/chrome/browser/ui/main/scene_controller.mm
+++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -992,15 +992,6 @@
 
 - (void)
     showReportAnIssueFromViewController:(UIViewController*)baseViewController
-                    specificProductData:(NSDictionary<NSString*, NSString*>*)
-                                            specificProductData {
-  [self showReportAnIssueFromViewController:baseViewController
-                                     sender:UserFeedbackSender::ToolsMenu
-                        specificProductData:specificProductData];
-}
-
-- (void)
-    showReportAnIssueFromViewController:(UIViewController*)baseViewController
                                  sender:(UserFeedbackSender)sender
                     specificProductData:(NSDictionary<NSString*, NSString*>*)
                                             specificProductData {
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc
index 0dbd0de8..8e9fb95 100644
--- a/media/blink/webmediaplayer_impl_unittest.cc
+++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -55,6 +55,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/media/webmediaplayer_delegate.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/public/platform/web_fullscreen_video_status.h"
 #include "third_party/blink/public/platform/web_media_player.h"
 #include "third_party/blink/public/platform/web_media_player_client.h"
@@ -332,13 +333,20 @@
       private blink::WebTestingSupport::WebScopedMockScrollbars {
  public:
   WebMediaPlayerImplTest()
+      : WebMediaPlayerImplTest(
+            blink::scheduler::WebThreadScheduler::MainThreadScheduler()
+                ->CreateAgentGroupScheduler()) {}
+  explicit WebMediaPlayerImplTest(
+      std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+          agent_group_scheduler)
       : media_thread_("MediaThreadForTest"),
         web_view_(blink::WebView::Create(/*client=*/nullptr,
                                          /*is_hidden=*/false,
                                          /*is_inside_portal=*/false,
                                          /*compositing_enabled=*/false,
-                                         nullptr,
-                                         mojo::NullAssociatedReceiver())),
+                                         /*opener=*/nullptr,
+                                         mojo::NullAssociatedReceiver(),
+                                         *agent_group_scheduler)),
         web_local_frame_(blink::WebLocalFrame::CreateMainFrame(
             web_view_,
             &web_frame_client_,
@@ -348,7 +356,8 @@
         context_provider_(viz::TestContextProvider::Create()),
         audio_parameters_(TestAudioParameters::Normal()),
         memory_dump_manager_(
-            base::trace_event::MemoryDumpManager::CreateInstanceForTesting()) {
+            base::trace_event::MemoryDumpManager::CreateInstanceForTesting()),
+        agent_group_scheduler_(std::move(agent_group_scheduler)) {
     media_thread_.StartAndWaitForTesting();
   }
 
@@ -382,6 +391,8 @@
     CycleThreads();
 
     web_view_->Close();
+
+    agent_group_scheduler_ = nullptr;
   }
 
  protected:
@@ -888,6 +899,9 @@
 
   std::unique_ptr<base::trace_event::MemoryDumpManager> memory_dump_manager_;
 
+  std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+      agent_group_scheduler_;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImplTest);
 };
diff --git a/media/capture/BUILD.gn b/media/capture/BUILD.gn
index b426e14..3c8a2fb 100644
--- a/media/capture/BUILD.gn
+++ b/media/capture/BUILD.gn
@@ -166,6 +166,8 @@
 
   if (is_mac) {
     sources += [
+      "video/mac/gpu_memory_buffer_tracker_mac.cc",
+      "video/mac/gpu_memory_buffer_tracker_mac.h",
       "video/mac/pixel_buffer_pool_mac.cc",
       "video/mac/pixel_buffer_pool_mac.h",
       "video/mac/pixel_buffer_transferer_mac.cc",
diff --git a/media/capture/video/chromeos/camera_3a_controller.cc b/media/capture/video/chromeos/camera_3a_controller.cc
index dc93a18e..16079425 100644
--- a/media/capture/video/chromeos/camera_3a_controller.cc
+++ b/media/capture/video/chromeos/camera_3a_controller.cc
@@ -397,6 +397,36 @@
   DVLOG(1) << "Setting AWB mode to: " << awb_mode_;
 }
 
+void Camera3AController::SetExposureTime(bool enable_auto,
+                                         int64_t exposure_time_nanoseconds) {
+  DCHECK(task_runner_->BelongsToCurrentThread());
+
+  if (enable_auto) {
+    if (!available_ae_modes_.count(
+            cros::mojom::AndroidControlAeMode::ANDROID_CONTROL_AE_MODE_ON)) {
+      LOG(WARNING) << "Don't support ANDROID_CONTROL_AE_MODE_ON";
+      return;
+    }
+    ae_mode_ = cros::mojom::AndroidControlAeMode::ANDROID_CONTROL_AE_MODE_ON;
+    capture_metadata_dispatcher_->UnsetRepeatingCaptureMetadata(
+        cros::mojom::CameraMetadataTag::ANDROID_SENSOR_EXPOSURE_TIME);
+  } else {
+    if (!available_ae_modes_.count(
+            cros::mojom::AndroidControlAeMode::ANDROID_CONTROL_AE_MODE_OFF)) {
+      LOG(WARNING) << "Don't support ANDROID_CONTROL_AE_MODE_OFF";
+      return;
+    }
+    ae_mode_ = cros::mojom::AndroidControlAeMode::ANDROID_CONTROL_AE_MODE_OFF;
+    SetRepeatingCaptureMetadata(
+        cros::mojom::CameraMetadataTag::ANDROID_SENSOR_EXPOSURE_TIME,
+        exposure_time_nanoseconds);
+  }
+
+  Set3AMode(cros::mojom::CameraMetadataTag::ANDROID_CONTROL_AE_MODE,
+            base::checked_cast<uint8_t>(ae_mode_));
+  DVLOG(1) << "Setting AE mode to: " << ae_mode_;
+}
+
 bool Camera3AController::IsPointOfInterestSupported() {
   return point_of_interest_supported_;
 }
diff --git a/media/capture/video/chromeos/camera_3a_controller.h b/media/capture/video/chromeos/camera_3a_controller.h
index 3a62006b..43d01a8 100644
--- a/media/capture/video/chromeos/camera_3a_controller.h
+++ b/media/capture/video/chromeos/camera_3a_controller.h
@@ -45,6 +45,11 @@
   // Set auto white balance mode.
   void SetAutoWhiteBalanceMode(cros::mojom::AndroidControlAwbMode mode);
 
+  // Set exposure time.
+  // |enable_auto| enables auto exposure mode. |exposure_time_nanoseconds| is
+  // only effective if |enable_auto| is set to false
+  void SetExposureTime(bool enable_auto, int64_t exposure_time_nanoseconds);
+
   bool IsPointOfInterestSupported();
 
   // Set point of interest. The coordinate system is based on the active
diff --git a/media/capture/video/chromeos/camera_device_delegate.cc b/media/capture/video/chromeos/camera_device_delegate.cc
index 4664908..3bf8c275 100644
--- a/media/capture/video/chromeos/camera_device_delegate.cc
+++ b/media/capture/video/chromeos/camera_device_delegate.cc
@@ -48,6 +48,7 @@
 constexpr char kZoom[] = "com.google.control.zoom";
 constexpr char kZoomRange[] = "com.google.control.zoomRange";
 constexpr int32_t kColorTemperatureStep = 100;
+constexpr int32_t kMicroToNano = 1000;
 
 using AwbModeTemperatureMap = std::map<uint8_t, int32_t>;
 
@@ -289,6 +290,7 @@
   is_set_awb_mode_ = false;
   is_set_brightness_ = false;
   is_set_contrast_ = false;
+  is_set_exposure_time_ = false;
   is_set_pan_ = false;
   is_set_saturation_ = false;
   is_set_sharpness_ = false;
@@ -509,6 +511,18 @@
     is_set_awb_mode_ = false;
   }
 
+  if (settings->has_exposure_mode &&
+      settings->exposure_mode == mojom::MeteringMode::MANUAL &&
+      settings->has_exposure_time) {
+    int64_t exposure_time_nanoseconds_ =
+        settings->exposure_time * 100 * kMicroToNano;
+    camera_3a_controller_->SetExposureTime(false, exposure_time_nanoseconds_);
+    is_set_exposure_time_ = true;
+  } else if (is_set_exposure_time_) {
+    camera_3a_controller_->SetExposureTime(true, 0);
+    is_set_exposure_time_ = false;
+  }
+
   bool is_resolution_specified = settings->has_width && settings->has_height;
   bool should_reconfigure_streams =
       is_resolution_specified && (current_blob_resolution_.IsEmpty() ||
@@ -1242,13 +1256,25 @@
         gfx::Rect(rect[0], rect[1], rect[2], rect[3]);
   }
 
+  result_metadata_.ae_mode.reset();
+  auto ae_mode = GetMetadataEntryAsSpan<uint8_t>(
+      result_metadata, cros::mojom::CameraMetadataTag::ANDROID_CONTROL_AE_MODE);
+  if (ae_mode.size() == 1)
+    result_metadata_.ae_mode = ae_mode[0];
+
+  result_metadata_.exposure_time.reset();
+  auto exposure_time = GetMetadataEntryAsSpan<int64_t>(
+      result_metadata,
+      cros::mojom::CameraMetadataTag::ANDROID_SENSOR_EXPOSURE_TIME);
+  if (exposure_time.size() == 1)
+    result_metadata_.exposure_time = exposure_time[0];
+
   result_metadata_.awb_mode.reset();
   auto awb_mode = GetMetadataEntryAsSpan<uint8_t>(
       result_metadata,
       cros::mojom::CameraMetadataTag::ANDROID_CONTROL_AWB_MODE);
-  if (awb_mode.size() == 1) {
+  if (awb_mode.size() == 1)
     result_metadata_.awb_mode = awb_mode[0];
-  }
 
   result_metadata_frame_number_ = frame_number;
   // We need to wait the new result metadata for new settings.
@@ -1382,6 +1408,45 @@
     photo_state->color_temperature->current = current_temperature;
   }
 
+  auto ae_available_modes = GetMetadataEntryAsSpan<uint8_t>(
+      static_metadata_,
+      cros::mojom::CameraMetadataTag::ANDROID_CONTROL_AE_AVAILABLE_MODES);
+  bool support_manual_exposure_time = false;
+  if (ae_available_modes.size() > 1 && result_metadata_.ae_mode) {
+    support_manual_exposure_time = base::Contains(
+        ae_available_modes,
+        static_cast<uint8_t>(
+            cros::mojom::AndroidControlAeMode::ANDROID_CONTROL_AE_MODE_OFF));
+  }
+
+  auto exposure_time_range = GetMetadataEntryAsSpan<int64_t>(
+      static_metadata_,
+      cros::mojom::CameraMetadataTag::ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE);
+
+  if (support_manual_exposure_time && exposure_time_range.size() == 2 &&
+      result_metadata_.exposure_time) {
+    photo_state->supported_exposure_modes.push_back(
+        mojom::MeteringMode::MANUAL);
+    photo_state->supported_exposure_modes.push_back(
+        mojom::MeteringMode::CONTINUOUS);
+    if (result_metadata_.ae_mode ==
+        static_cast<uint8_t>(
+            cros::mojom::AndroidControlAeMode::ANDROID_CONTROL_AE_MODE_OFF))
+      photo_state->current_exposure_mode = mojom::MeteringMode::MANUAL;
+    else
+      photo_state->current_exposure_mode = mojom::MeteringMode::CONTINUOUS;
+
+    // The unit of photo_state->exposure_time is 100 microseconds and from
+    // metadata is nanoseconds.
+    photo_state->exposure_time->min = std::ceil(
+        static_cast<float>(exposure_time_range[0]) / (100 * kMicroToNano));
+    photo_state->exposure_time->max =
+        exposure_time_range[1] / (100 * kMicroToNano);
+    photo_state->exposure_time->step = 1;  // 100 microseconds
+    photo_state->exposure_time->current =
+        result_metadata_.exposure_time.value() / (100 * kMicroToNano);
+  }
+
   std::move(callback).Run(std::move(photo_state));
 }
 
diff --git a/media/capture/video/chromeos/camera_device_delegate.h b/media/capture/video/chromeos/camera_device_delegate.h
index 78868a5..f678b8f 100644
--- a/media/capture/video/chromeos/camera_device_delegate.h
+++ b/media/capture/video/chromeos/camera_device_delegate.h
@@ -42,9 +42,11 @@
   ResultMetadata();
   ~ResultMetadata();
 
+  base::Optional<uint8_t> ae_mode;
   base::Optional<uint8_t> awb_mode;
   base::Optional<int32_t> brightness;
   base::Optional<int32_t> contrast;
+  base::Optional<int64_t> exposure_time;
   base::Optional<int32_t> pan;
   base::Optional<int32_t> saturation;
   base::Optional<int32_t> sharpness;
@@ -244,6 +246,7 @@
   bool is_set_awb_mode_;
   bool is_set_brightness_;
   bool is_set_contrast_;
+  bool is_set_exposure_time_;
   bool is_set_pan_;
   bool is_set_saturation_;
   bool is_set_sharpness_;
diff --git a/media/capture/video/file_video_capture_device.cc b/media/capture/video/file_video_capture_device.cc
index 4b5af3b..41daa799 100644
--- a/media/capture/video/file_video_capture_device.cc
+++ b/media/capture/video/file_video_capture_device.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/location.h"
+#include "base/logging.h"
 #include "base/macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
@@ -453,6 +454,7 @@
         VideoCaptureDevice::Client::ReserveResult::kSucceeded) {
       client_->OnFrameDropped(
           ConvertReservationFailureToFrameDropReason(reserve_result));
+      DVLOG(2) << __func__ << " frame was dropped.";
       return;
     }
     ScopedNV12GpuMemoryBufferMapping scoped_mapping(std::move(gmb));
@@ -469,7 +471,6 @@
         src_v_plane, buffer_size.width() / 2, scoped_mapping.y_plane(),
         scoped_mapping.y_stride(), scoped_mapping.uv_plane(),
         scoped_mapping.uv_stride(), buffer_size.width(), buffer_size.height());
-
     VideoCaptureFormat modified_format = capture_format_;
     // When GpuMemoryBuffer is used, the frame data is opaque to the CPU for
     // most of the time.  Currently the only supported underlying format is
diff --git a/media/capture/video/mac/gpu_memory_buffer_tracker_mac.cc b/media/capture/video/mac/gpu_memory_buffer_tracker_mac.cc
new file mode 100644
index 0000000..73d4190
--- /dev/null
+++ b/media/capture/video/mac/gpu_memory_buffer_tracker_mac.cc
@@ -0,0 +1,76 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/capture/video/mac/gpu_memory_buffer_tracker_mac.h"
+
+#include "base/logging.h"
+
+namespace media {
+
+GpuMemoryBufferTrackerMac::GpuMemoryBufferTrackerMac() {}
+
+GpuMemoryBufferTrackerMac::~GpuMemoryBufferTrackerMac() {}
+
+bool GpuMemoryBufferTrackerMac::Init(const gfx::Size& dimensions,
+                                     VideoPixelFormat format,
+                                     const mojom::PlaneStridesPtr& strides) {
+  if (format != PIXEL_FORMAT_NV12) {
+    NOTREACHED() << "Unsupported VideoPixelFormat "
+                 << VideoPixelFormatToString(format);
+    return false;
+  }
+  if (IOSurfaceRef io_surface =
+          CreateIOSurface(dimensions, gfx::BufferFormat::YUV_420_BIPLANAR,
+                          /*should_clear=*/false)) {
+    io_surface_.reset(io_surface, base::scoped_policy::ASSUME);
+    DVLOG(2) << __func__ << " id " << IOSurfaceGetID(io_surface_);
+    return true;
+  } else {
+    LOG(ERROR) << "Unable to create IOSurface!";
+    return false;
+  }
+}
+
+bool GpuMemoryBufferTrackerMac::IsReusableForFormat(
+    const gfx::Size& dimensions,
+    VideoPixelFormat format,
+    const mojom::PlaneStridesPtr& strides) {
+  gfx::Size surface_size(IOSurfaceGetWidth(io_surface_),
+                         IOSurfaceGetHeight(io_surface_));
+  return format == PIXEL_FORMAT_NV12 && dimensions == surface_size;
+}
+
+uint32_t GpuMemoryBufferTrackerMac::GetMemorySizeInBytes() {
+  return IOSurfaceGetAllocSize(io_surface_);
+}
+
+std::unique_ptr<VideoCaptureBufferHandle>
+GpuMemoryBufferTrackerMac::GetMemoryMappedAccess() {
+  NOTREACHED() << "Unsupported operation";
+  return std::make_unique<NullHandle>();
+}
+
+base::UnsafeSharedMemoryRegion
+GpuMemoryBufferTrackerMac::DuplicateAsUnsafeRegion() {
+  NOTREACHED() << "Unsupported operation";
+  return base::UnsafeSharedMemoryRegion();
+}
+
+mojo::ScopedSharedBufferHandle
+GpuMemoryBufferTrackerMac::DuplicateAsMojoBuffer() {
+  NOTREACHED() << "Unsupported operation";
+  return mojo::ScopedSharedBufferHandle();
+}
+
+gfx::GpuMemoryBufferHandle
+GpuMemoryBufferTrackerMac::GetGpuMemoryBufferHandle() {
+  DVLOG(2) << __func__ << " id " << IOSurfaceGetID(io_surface_);
+  gfx::GpuMemoryBufferHandle gmb_handle;
+  gmb_handle.type = gfx::GpuMemoryBufferType::IO_SURFACE_BUFFER;
+  gmb_handle.id.id = -1;
+  gmb_handle.io_surface = io_surface_;
+  return gmb_handle;
+}
+
+}  // namespace media
diff --git a/media/capture/video/mac/gpu_memory_buffer_tracker_mac.h b/media/capture/video/mac/gpu_memory_buffer_tracker_mac.h
new file mode 100644
index 0000000..857c20c
--- /dev/null
+++ b/media/capture/video/mac/gpu_memory_buffer_tracker_mac.h
@@ -0,0 +1,41 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CAPTURE_VIDEO_MAC_GPU_MEMORY_BUFFER_TRACKER_MAC_H_
+#define MEDIA_CAPTURE_VIDEO_MAC_GPU_MEMORY_BUFFER_TRACKER_MAC_H_
+
+#include "media/capture/video/video_capture_buffer_tracker.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/mac/io_surface.h"
+
+namespace media {
+
+class CAPTURE_EXPORT GpuMemoryBufferTrackerMac final
+    : public VideoCaptureBufferTracker {
+ public:
+  GpuMemoryBufferTrackerMac();
+  ~GpuMemoryBufferTrackerMac() override;
+
+  // VideoCaptureBufferTracker
+  bool Init(const gfx::Size& dimensions,
+            VideoPixelFormat format,
+            const mojom::PlaneStridesPtr& strides) override;
+  bool IsReusableForFormat(const gfx::Size& dimensions,
+                           VideoPixelFormat format,
+                           const mojom::PlaneStridesPtr& strides) override;
+  uint32_t GetMemorySizeInBytes() override;
+  std::unique_ptr<VideoCaptureBufferHandle> GetMemoryMappedAccess() override;
+  base::UnsafeSharedMemoryRegion DuplicateAsUnsafeRegion() override;
+  mojo::ScopedSharedBufferHandle DuplicateAsMojoBuffer() override;
+  gfx::GpuMemoryBufferHandle GetGpuMemoryBufferHandle() override;
+
+ private:
+  base::ScopedCFTypeRef<IOSurfaceRef> io_surface_;
+
+  DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferTrackerMac);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_CAPTURE_VIDEO_MAC_GPU_MEMORY_BUFFER_TRACKER_MAC_H_
\ No newline at end of file
diff --git a/media/capture/video/video_capture_buffer_pool_impl.cc b/media/capture/video/video_capture_buffer_pool_impl.cc
index 64180e4..51ca09a 100644
--- a/media/capture/video/video_capture_buffer_pool_impl.cc
+++ b/media/capture/video/video_capture_buffer_pool_impl.cc
@@ -242,6 +242,8 @@
     if (tracker_to_drop == trackers_.end()) {
       // We're out of space, and can't find an unused tracker to reallocate.
       *buffer_id = kInvalidId;
+      DLOG(ERROR) << __func__
+                  << " max buffer count exceeded count_ = " << count_;
       return VideoCaptureDevice::Client::ReserveResult::kMaxBufferCountExceeded;
     }
     *buffer_id_to_drop = tracker_to_drop->first;
diff --git a/media/capture/video/video_capture_buffer_tracker_factory_impl.cc b/media/capture/video/video_capture_buffer_tracker_factory_impl.cc
index bf664776..69373623 100644
--- a/media/capture/video/video_capture_buffer_tracker_factory_impl.cc
+++ b/media/capture/video/video_capture_buffer_tracker_factory_impl.cc
@@ -7,12 +7,17 @@
 #include <memory>
 #include "build/chromeos_buildflags.h"
 
+#include "build/build_config.h"
 #include "media/capture/video/shared_memory_buffer_tracker.h"
 
 #if BUILDFLAG(IS_ASH)
 #include "media/capture/video/chromeos/gpu_memory_buffer_tracker.h"
 #endif
 
+#if defined(OS_MAC)
+#include "media/capture/video/mac/gpu_memory_buffer_tracker_mac.h"
+#endif
+
 namespace media {
 
 std::unique_ptr<VideoCaptureBufferTracker>
@@ -22,6 +27,8 @@
     case VideoCaptureBufferType::kGpuMemoryBuffer:
 #if BUILDFLAG(IS_ASH)
       return std::make_unique<GpuMemoryBufferTracker>();
+#elif defined(OS_MAC)
+      return std::make_unique<GpuMemoryBufferTrackerMac>();
 #else
       return nullptr;
 #endif
diff --git a/media/capture/video/video_capture_device_client.cc b/media/capture/video/video_capture_device_client.cc
index ec92e19..50db22f 100644
--- a/media/capture/video/video_capture_device_client.cc
+++ b/media/capture/video/video_capture_device_client.cc
@@ -558,8 +558,10 @@
       receiver_->OnBufferRetired(buffer_id_to_drop);
     }
   }
-  if (reservation_result_code != ReserveResult::kSucceeded)
+  if (reservation_result_code != ReserveResult::kSucceeded) {
+    DVLOG(2) << __func__ << " reservation failed";
     return reservation_result_code;
+  }
 
   DCHECK_NE(VideoCaptureBufferPool::kInvalidId, buffer_id);
 
diff --git a/media/gpu/mac/vt_video_encode_accelerator_mac.cc b/media/gpu/mac/vt_video_encode_accelerator_mac.cc
index 2fa16ce..dce3bab 100644
--- a/media/gpu/mac/vt_video_encode_accelerator_mac.cc
+++ b/media/gpu/mac/vt_video_encode_accelerator_mac.cc
@@ -142,7 +142,8 @@
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(client);
 
-  if (PIXEL_FORMAT_I420 != config.input_format) {
+  if (config.input_format != PIXEL_FORMAT_I420 &&
+      config.input_format != PIXEL_FORMAT_NV12) {
     DLOG(ERROR) << "Input format not supported= "
                 << VideoPixelFormatToString(config.input_format);
     return false;
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
index 9d7aec4..f765bea63 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -1502,9 +1502,10 @@
   output_buffer_byte_size_ =
       GetEncodeBitstreamBufferSize(encoder_input_visible_rect_.size());
 
+  // Sets 0 to width and height in CAPTURE queue, which should be ignored by the
+  // driver.
   base::Optional<struct v4l2_format> format = output_queue_->SetFormat(
-      output_format_fourcc_, encoder_input_visible_rect_.size(),
-      output_buffer_byte_size_);
+      output_format_fourcc_, gfx::Size(), output_buffer_byte_size_);
   if (!format) {
     return false;
   }
diff --git a/sandbox/policy/mac/gpu_v2.sb b/sandbox/policy/mac/gpu_v2.sb
index 8b969c8..1bb5edc 100644
--- a/sandbox/policy/mac/gpu_v2.sb
+++ b/sandbox/policy/mac/gpu_v2.sb
@@ -16,7 +16,7 @@
 
 ; TODO(https://crbug.com/1126350): Remove this after debugging. These blocks
 ; enumerate known denials, while turning unknown denials into fatal crashes.
-(define crash-on-unknown-denials #t) ; Single-line kill switch.
+(define crash-on-unknown-denials #f) ; Single-line kill switch.
 (if crash-on-unknown-denials
   (begin
     (deny mach-lookup (with no-report)
@@ -49,7 +49,6 @@
       (subpath (param bundle-path))
     )
     (deny file-write* (with send-signal SIGSYS))
-    (deny sysctl-read (with send-signal SIGSYS))
   )
 )
 
diff --git a/services/video_capture/device_media_to_mojo_adapter.cc b/services/video_capture/device_media_to_mojo_adapter.cc
index 93a730f..03d6643 100644
--- a/services/video_capture/device_media_to_mojo_adapter.cc
+++ b/services/video_capture/device_media_to_mojo_adapter.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/check.h"
 #include "base/command_line.h"
+#include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/capture/capture_switches.h"
@@ -177,7 +178,11 @@
   // those frames get dropped.
   static int kMaxBufferCount = 3;
 
-#if BUILDFLAG(IS_ASH)
+#if defined(OS_MAC)
+  // On macOS, we allow a few more buffers as it's routinely observed that it
+  // runs out of three when just displaying 60 FPS media in a video element.
+  kMaxBufferCount = 10;
+#elif BUILDFLAG(IS_ASH)
   // On Chrome OS with MIPI cameras running on HAL v3, there can be three
   // concurrent streams of camera pipeline depth ~6. We allow at most 30 buffers
   // here to take into account the delay caused by the consumer (e.g. display or
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index 873d7df..f2862c8 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -3037,6 +3037,7 @@
   kUnicodeBidiPlainText = 3706,
   kColorSchemeDarkSupportedOnRoot = 3707,
   kWebBluetoothGetAvailability = 3708,
+  kDigitalGoodsListPurchases = 3709,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h b/third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h
index ebbcaeb7..70d6f2e 100644
--- a/third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h
+++ b/third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h
@@ -9,6 +9,7 @@
 #include "third_party/blink/public/platform/web_common.h"
 
 namespace blink {
+class AgentGroupScheduler;
 namespace scheduler {
 
 // WebAgentGroupScheduler schedules per-AgentSchedulingGroup tasks.
@@ -18,8 +19,14 @@
 // run on a different WebAgentGroupScheduler.
 class BLINK_PLATFORM_EXPORT WebAgentGroupScheduler {
  public:
+  // Create a dummy AgentGroupScheduler only for testing
+  static std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+  CreateForTesting();
+
   virtual ~WebAgentGroupScheduler() = default;
 
+  virtual AgentGroupScheduler& AsAgentGroupScheduler() = 0;
+
   // Default task runner for an AgentSchedulingGroup.
   // Default task runners for different AgentSchedulingGroup would be
   // independent and won't have any ordering guarantees between them.
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h
index fa26383..747166a 100644
--- a/third_party/blink/public/web/web_local_frame.h
+++ b/third_party/blink/public/web/web_local_frame.h
@@ -56,6 +56,10 @@
 
 namespace blink {
 
+namespace scheduler {
+class WebAgentGroupScheduler;
+}  // namespace scheduler
+
 class FrameScheduler;
 class InterfaceRegistry;
 class WebAssociatedURLLoader;
@@ -605,8 +609,12 @@
 
   // Scheduling ---------------------------------------------------------------
 
+  // Returns FrameScheduler
   virtual FrameScheduler* Scheduler() const = 0;
 
+  // Returns AgentGroupScheduler
+  virtual scheduler::WebAgentGroupScheduler* GetAgentGroupScheduler() const = 0;
+
   // Task queues --------------------------------------------------------------
 
   // Returns frame-specific task runner to run tasks of this type on.
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h
index dd30789..5b9b882 100644
--- a/third_party/blink/public/web/web_view.h
+++ b/third_party/blink/public/web/web_view.h
@@ -39,6 +39,7 @@
 #include "third_party/blink/public/mojom/page/page_visibility_state.mojom-shared.h"
 #include "third_party/blink/public/mojom/widget/screen_orientation.mojom-shared.h"
 #include "third_party/blink/public/platform/cross_variant_mojo_util.h"
+#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/web/web_settings.h"
@@ -110,7 +111,8 @@
       bool compositing_enabled,
       WebView* opener,
       CrossVariantMojoAssociatedReceiver<mojom::PageBroadcastInterfaceBase>
-          page_handle);
+          page_handle,
+      scheduler::WebAgentGroupScheduler& agent_group_scheduler);
 
   // Destroys the WebView.
   virtual void Close() = 0;
diff --git a/third_party/blink/renderer/bindings/BUILD.gn b/third_party/blink/renderer/bindings/BUILD.gn
index 6a457ce..fc7afc3c 100644
--- a/third_party/blink/renderer/bindings/BUILD.gn
+++ b/third_party/blink/renderer/bindings/BUILD.gn
@@ -225,6 +225,9 @@
                generated_interface_sources_in_modules +
                generated_interface_sources_for_testing_in_core +
                generated_interface_sources_for_testing_in_modules
+    targets += [ "namespace" ]
+    outputs += generated_namespace_sources_in_core +
+               generated_namespace_sources_in_modules
   }
 }
 
diff --git a/third_party/blink/renderer/bindings/core/v8/BUILD.gn b/third_party/blink/renderer/bindings/core/v8/BUILD.gn
index e3df5db0..a0c14c2 100644
--- a/third_party/blink/renderer/bindings/core/v8/BUILD.gn
+++ b/third_party/blink/renderer/bindings/core/v8/BUILD.gn
@@ -27,7 +27,8 @@
     sources += generated_dictionary_sources_in_core
   }
   if (use_blink_v8_binding_new_idl_interface) {
-    sources += generated_interface_sources_in_core
+    sources += generated_interface_sources_in_core +
+               generated_namespace_sources_in_core
   }
 
   deps = [
diff --git a/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc b/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc
index 7d338b7a..fb3b0e8 100644
--- a/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc
+++ b/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc
@@ -160,7 +160,7 @@
 
 namespace bindings {
 
-void SetupIDLInterfaceTemplates(
+void SetupIDLInterfaceTemplate(
     v8::Isolate* isolate,
     const WrapperTypeInfo* wrapper_type_info,
     v8::Local<v8::ObjectTemplate> instance_template,
@@ -186,7 +186,12 @@
     v8::Isolate* isolate,
     const WrapperTypeInfo* wrapper_type_info,
     v8::Local<v8::ObjectTemplate> interface_template) {
-  // TODO(yukishiino): To be implemented.
+  v8::Local<v8::String> class_string =
+      V8AtomicString(isolate, wrapper_type_info->interface_name);
+
+  interface_template->Set(
+      v8::Symbol::GetToStringTag(isolate), class_string,
+      static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
 }
 
 void SetupIDLCallbackInterfaceTemplate(
diff --git a/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h b/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h
index 7209816..a0582c93 100644
--- a/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h
+++ b/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h
@@ -99,7 +99,7 @@
 
 namespace bindings {
 
-CORE_EXPORT void SetupIDLInterfaceTemplates(
+CORE_EXPORT void SetupIDLInterfaceTemplate(
     v8::Isolate* isolate,
     const WrapperTypeInfo* wrapper_type_info,
     v8::Local<v8::ObjectTemplate> instance_template,
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni
index afc5627..dc23ddb6 100644
--- a/third_party/blink/renderer/bindings/generated_in_core.gni
+++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -1391,6 +1391,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_xslt_processor.h",
 ]
 
+generated_namespace_sources_in_core = []
+
 # Generated sources for testing
 
 generated_callback_function_sources_for_testing_in_core = [
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index ecb0debe..b4080f8 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -2217,7 +2217,23 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_world_tracking_state.h",
 ]
 
-# Serial and Direct Sockets
+generated_namespace_sources_in_modules = []
+
+# Direct Sockets
+if (!is_android) {
+  generated_dictionary_sources_in_modules += [
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_socket_options.cc",
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_socket_options.h",
+  ]
+  generated_interface_sources_in_modules += [
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_tcp_socket.cc",
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_tcp_socket.h",
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_udp_socket.cc",
+    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_udp_socket.h",
+  ]
+}
+
+# Serial
 if (!is_android) {
   generated_dictionary_sources_in_modules += [
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_serial_connection_event_init.cc",
@@ -2234,8 +2250,6 @@
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_serial_port_info.h",
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_serial_port_request_options.cc",
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_serial_port_request_options.h",
-    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_socket_options.cc",
-    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_socket_options.h",
   ]
   generated_enumeration_sources_in_modules += [
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_flow_control_type.cc",
@@ -2250,10 +2264,6 @@
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_serial_connection_event.h",
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_serial_port.cc",
     "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_serial_port.h",
-    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_tcp_socket.cc",
-    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_tcp_socket.h",
-    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_udp_socket.cc",
-    "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_udp_socket.h",
   ]
 }
 
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni
index 091e878..00eec643 100644
--- a/third_party/blink/renderer/bindings/idl_in_modules.gni
+++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -251,6 +251,7 @@
           "//third_party/blink/renderer/modules/font_access/font_metadata.idl",
           "//third_party/blink/renderer/modules/font_access/font_table_map.idl",
           "//third_party/blink/renderer/modules/font_access/navigator_fonts.idl",
+          "//third_party/blink/renderer/modules/font_access/query_options.idl",
           "//third_party/blink/renderer/modules/gamepad/gamepad.idl",
           "//third_party/blink/renderer/modules/gamepad/gamepad_axis_event.idl",
           "//third_party/blink/renderer/modules/gamepad/gamepad_axis_event_init.idl",
@@ -1019,14 +1020,22 @@
         ],
         "abspath")
 
-# Serial and Direct Sockets
+# Direct Sockets
 if (!is_android) {
   static_idl_files_in_modules += get_path_info(
           [
             "//third_party/blink/renderer/modules/direct_sockets/navigator_socket.idl",
+            "//third_party/blink/renderer/modules/direct_sockets/socket_options.idl",
             "//third_party/blink/renderer/modules/direct_sockets/tcp_socket.idl",
             "//third_party/blink/renderer/modules/direct_sockets/udp_socket.idl",
-            "//third_party/blink/renderer/modules/direct_sockets/socket_options.idl",
+          ],
+          "abspath")
+}
+
+# Serial
+if (!is_android) {
+  static_idl_files_in_modules += get_path_info(
+          [
             "//third_party/blink/renderer/modules/serial/navigator_serial.idl",
             "//third_party/blink/renderer/modules/serial/serial.idl",
             "//third_party/blink/renderer/modules/serial/serial_connection_event.idl",
diff --git a/third_party/blink/renderer/bindings/modules/v8/BUILD.gn b/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
index 3a7ae90e..92d0b2c 100644
--- a/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
+++ b/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
@@ -26,7 +26,8 @@
     sources += generated_dictionary_sources_in_modules
   }
   if (use_blink_v8_binding_new_idl_interface) {
-    sources += generated_interface_sources_in_modules
+    sources += generated_interface_sources_in_modules +
+               generated_namespace_sources_in_modules
   }
 
   deps = [
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py b/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py
index 1142a61..49a34538 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py
@@ -38,6 +38,7 @@
 from .dictionary import generate_dictionaries
 from .enumeration import generate_enumerations
 from .interface import generate_interfaces
+from .namespace import generate_namespaces
 from .task_queue import TaskQueue
 
 
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
index b7e4918..9f554ce 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -2024,11 +2024,18 @@
     func_def = _make_empty_callback_def(cg_context, function_name)
     body = func_def.body
 
+    if (cg_context.exposed_construct.is_interface
+            or cg_context.exposed_construct.is_callback_interface):
+        tag = "bindings::V8ReturnValue::kInterfaceObject"
+    elif cg_context.exposed_construct.is_namespace:
+        tag = "bindings::V8ReturnValue::kNamespaceObject"
+    else:
+        assert False
     v8_set_return_value = _format(
         "bindings::V8SetReturnValue"
-        "(${info}, {}::GetWrapperTypeInfo(), "
-        "bindings::V8ReturnValue::kInterfaceObject);",
-        v8_bridge_class_name(cg_context.exposed_construct))
+        "(${info}, {bridge}::GetWrapperTypeInfo(), {tag});",
+        bridge=v8_bridge_class_name(cg_context.exposed_construct),
+        tag=tag)
     body.extend([
         make_runtime_call_timer_scope(cg_context),
         make_bindings_trace_event(cg_context),
@@ -4215,6 +4222,10 @@
         ])
     elif cg_context.namespace:
         local_vars.extend([
+            S("namespace_object_template",
+              ("v8::Local<v8::ObjectTemplate> "
+               "${namespace_object_template} = "
+               "${interface_template}.As<v8::ObjectTemplate>();")),
             S("instance_template",
               "v8::Local<v8::Template> ${instance_template};"),
             S("prototype_template",
@@ -5135,7 +5146,7 @@
 
     if cg_context.interface:
         body.extend([
-            T("bindings::SetupIDLInterfaceTemplates("
+            T("bindings::SetupIDLInterfaceTemplate("
               "${isolate}, ${wrapper_type_info}, "
               "${instance_object_template}, "
               "${prototype_object_template}, "
@@ -5147,7 +5158,7 @@
         body.extend([
             T("bindings::SetupIDLNamespaceTemplate("
               "${isolate}, ${wrapper_type_info}, "
-              "${interface_function_template});"),
+              "${namespace_object_template});"),
             EmptyNode(),
         ])
     elif cg_context.callback_interface:
@@ -5508,7 +5519,7 @@
     ])
 
     if (is_per_context_install
-            and "Global" in cg_context.interface.extended_attributes):
+            and "Global" in cg_context.class_like.extended_attributes):
         body.extend([
             CxxLikelyIfNode(cond="${instance_object}.IsEmpty()",
                             body=[
@@ -5878,7 +5889,7 @@
     install_node = SequenceNode()
 
     CROSS_ORIGIN_INTERFACES = ("Window", "Location")
-    if cg_context.interface.identifier not in CROSS_ORIGIN_INTERFACES:
+    if cg_context.class_like.identifier not in CROSS_ORIGIN_INTERFACES:
         return callback_defs, install_node
     props = cg_context.interface.indexed_and_named_properties
 
@@ -6300,6 +6311,9 @@
     assert isinstance(cg_context, CodeGenContext)
     assert isinstance(component, web_idl.Component)
 
+    if not cg_context.interface:
+        return None, None
+
     derived_interfaces = cg_context.interface.deriveds
     derived_names = map(lambda interface: interface.identifier,
                         derived_interfaces)
@@ -6472,10 +6486,10 @@
 # ----------------------------------------------------------------------------
 
 
-def _collect_include_headers(interface):
-    assert isinstance(interface, web_idl.Interface)
+def _collect_include_headers(class_like):
+    assert isinstance(class_like, (web_idl.Interface, web_idl.Namespace))
 
-    headers = set(interface.code_generator_info.blink_headers)
+    headers = set(class_like.code_generator_info.blink_headers)
 
     def collect_from_idl_type(idl_type):
         idl_type.apply_to_all_composing_elements(add_include_headers)
@@ -6493,7 +6507,7 @@
                 raise StopIteration(idl_type.syntactic_form)
 
             headers.add(PathManager(type_def_obj).api_path(ext="h"))
-            if isinstance(type_def_obj, web_idl.Interface):
+            if type_def_obj.is_interface or type_def_obj.is_namespace:
                 headers.add(PathManager(type_def_obj).blink_path(ext="h"))
             raise StopIteration(idl_type.syntactic_form)
 
@@ -6501,23 +6515,24 @@
         if union_def_obj is not None:
             headers.add(PathManager(union_def_obj).api_path(ext="h"))
 
-    for attribute in interface.attributes:
+    for attribute in class_like.attributes:
         collect_from_idl_type(attribute.idl_type)
-    for constructor in interface.constructors:
+    for constructor in class_like.constructors:
         for argument in constructor.arguments:
             collect_from_idl_type(argument.idl_type)
-    for operation in interface.operations:
+    for operation in class_like.operations:
         collect_from_idl_type(operation.return_type)
         for argument in operation.arguments:
             collect_from_idl_type(argument.idl_type)
 
-    for exposed_construct in interface.exposed_constructs:
-        headers.add(PathManager(exposed_construct).api_path(ext="h"))
-    for legacy_window_alias in interface.legacy_window_aliases:
-        headers.add(
-            PathManager(legacy_window_alias.original).api_path(ext="h"))
+    if class_like.is_interface:
+        for exposed_construct in class_like.exposed_constructs:
+            headers.add(PathManager(exposed_construct).api_path(ext="h"))
+        for legacy_window_alias in class_like.legacy_window_aliases:
+            headers.add(
+                PathManager(legacy_window_alias.original).api_path(ext="h"))
 
-    path_manager = PathManager(interface)
+    path_manager = PathManager(class_like)
     headers.discard(path_manager.api_path(ext="h"))
     headers.discard(path_manager.impl_path(ext="h"))
 
@@ -6525,32 +6540,38 @@
     # [ImplementedAs=LocalDOMWindow] instead of [ImplementedAs=DOMWindow], and
     # [CrossOrigin] properties should be implemented specifically with
     # DOMWindow class.  Then, we'll have less hacks.
-    if interface.identifier == "Window":
+    if class_like.identifier == "Window":
         headers.add("third_party/blink/renderer/core/frame/local_dom_window.h")
 
     return headers
 
 
-def generate_interface(interface_identifier):
-    assert isinstance(interface_identifier, web_idl.Identifier)
+def generate_class_like(class_like):
+    assert isinstance(class_like, (web_idl.Interface, web_idl.Namespace))
 
-    web_idl_database = package_initializer().web_idl_database()
-    interface = web_idl_database.find(interface_identifier)
-
-    path_manager = PathManager(interface)
+    path_manager = PathManager(class_like)
     api_component = path_manager.api_component
     impl_component = path_manager.impl_component
     is_cross_components = path_manager.is_cross_components
-    for_testing = interface.code_generator_info.for_testing
+    for_testing = class_like.code_generator_info.for_testing
 
     # Class names
-    api_class_name = v8_bridge_class_name(interface)
+    api_class_name = v8_bridge_class_name(class_like)
     if is_cross_components:
         impl_class_name = "{}::Impl".format(api_class_name)
     else:
         impl_class_name = api_class_name
 
-    cg_context = CodeGenContext(interface=interface, class_name=api_class_name)
+    interface = None
+    namespace = None
+    if class_like.is_interface:
+        interface = class_like
+        cg_context = CodeGenContext(interface=interface,
+                                    class_name=api_class_name)
+    elif class_like.is_namespace:
+        namespace = class_like
+        cg_context = CodeGenContext(namespace=namespace,
+                                    class_name=api_class_name)
 
     # Filepaths
     api_header_path = path_manager.api_path(ext="h")
@@ -6592,13 +6613,13 @@
         cg_context.class_name,
         base_class_names=[
             _format("bindings::V8InterfaceBridge<${class_name}, {}>",
-                    blink_class_name(interface)),
+                    blink_class_name(class_like)),
         ],
         final=True,
         export=component_export(api_component, for_testing))
     api_class_def.set_base_template_vars(cg_context.template_bindings())
     api_class_def.bottom_section.append(
-        TextNode("friend class {};".format(blink_class_name(interface))))
+        TextNode("friend class {};".format(blink_class_name(class_like))))
     if is_cross_components:
         impl_class_def = CxxClassDefNode(impl_class_name,
                                          final=True,
@@ -6615,10 +6636,10 @@
 
     # Constants
     constants_def = None
-    if interface.constants:
+    if class_like.constants:
         constants_def = CxxClassDefNode(name="Constant", final=True)
         constants_def.top_section.append(TextNode("STATIC_ONLY(Constant);"))
-        for constant in interface.constants:
+        for constant in class_like.constants:
             cgc = cg_context.make_copy(constant=constant)
             constants_def.public_section.append(
                 make_constant_constant_def(cgc, constant_name(cgc)))
@@ -6638,11 +6659,11 @@
                 return_type="void",
                 static=True))
 
-    if interface.identifier == "HTMLAllCollection":
+    if class_like.identifier == "HTMLAllCollection":
         add_custom_callback_impl_decl(
             name=name_style.func("LegacyCallCustom"),
             arg_decls=["const v8::FunctionCallbackInfo<v8::Value>&"])
-    for attribute in interface.attributes:
+    for attribute in class_like.attributes:
         custom_values = attribute.extended_attributes.values_of("Custom")
         is_cross_origin = "CrossOrigin" in attribute.extended_attributes
         cross_origin_values = attribute.extended_attributes.values_of(
@@ -6675,12 +6696,12 @@
                         "v8::Local<v8::Value>",
                         "const v8::PropertyCallbackInfo<void>&",
                     ])
-    for operation_group in interface.operation_groups:
+    for operation_group in class_like.operation_groups:
         if "Custom" in operation_group.extended_attributes:
             add_custom_callback_impl_decl(
                 operation_group=operation_group,
                 arg_decls=["const v8::FunctionCallbackInfo<v8::Value>&"])
-    if interface.indexed_and_named_properties:
+    if interface and interface.indexed_and_named_properties:
         props = interface.indexed_and_named_properties
         operation = props.own_named_getter
         if operation and "Custom" in operation.extended_attributes:
@@ -6929,11 +6950,11 @@
             EmptyNode(),
         ])
     api_header_node.accumulator.add_include_headers([
-        interface.code_generator_info.blink_headers[0],
+        class_like.code_generator_info.blink_headers[0],
         component_export_header(api_component, for_testing),
         "third_party/blink/renderer/platform/bindings/v8_interface_bridge.h",
     ])
-    if interface.inherited:
+    if interface and interface.inherited:
         api_source_node.accumulator.add_include_headers(
             [PathManager(interface.inherited).api_path(ext="h")])
     if is_cross_components:
@@ -6951,7 +6972,7 @@
         "third_party/blink/renderer/platform/bindings/v8_binding.h",
     ])
     impl_source_node.accumulator.add_include_headers(
-        _collect_include_headers(interface))
+        _collect_include_headers(class_like))
 
     # Assemble the parts.
     api_header_blink_ns.body.extend([
@@ -7052,6 +7073,15 @@
                                 path_manager.gen_path_to(impl_source_path))
 
 
+def generate_interface(interface_identifier):
+    assert isinstance(interface_identifier, web_idl.Identifier)
+
+    web_idl_database = package_initializer().web_idl_database()
+    interface = web_idl_database.find(interface_identifier)
+
+    generate_class_like(interface)
+
+
 def generate_install_properties_per_feature(function_name,
                                             filepath_basename,
                                             for_testing=False):
@@ -7164,25 +7194,27 @@
     ])
 
     # The public function
-    feature_to_interfaces = {}
-    set_of_interfaces = set()
-    for interface in web_idl_database.interfaces:
-        if interface.code_generator_info.for_testing != for_testing:
+    feature_to_class_likes = {}
+    set_of_class_likes = set()
+    for class_like in itertools.chain(web_idl_database.interfaces,
+                                      web_idl_database.namespaces):
+        if class_like.code_generator_info.for_testing != for_testing:
             continue
 
-        for member in itertools.chain(interface.attributes,
-                                      interface.constants,
-                                      interface.operation_groups,
-                                      interface.exposed_constructs):
+        for member in itertools.chain(class_like.attributes,
+                                      class_like.constants,
+                                      class_like.operation_groups,
+                                      class_like.exposed_constructs):
             features = list(
                 member.exposure.context_dependent_runtime_enabled_features)
             for entry in member.exposure.global_names_and_features:
                 if entry.feature and entry.feature.is_context_dependent:
                     features.append(entry.feature)
             for feature in features:
-                feature_to_interfaces.setdefault(feature, set()).add(interface)
+                feature_to_class_likes.setdefault(feature,
+                                                  set()).add(class_like)
             if features:
-                set_of_interfaces.add(interface)
+                set_of_class_likes.add(class_like)
 
     switch_node = CxxSwitchNode(cond="${feature}")
     switch_node.append(
@@ -7192,13 +7224,13 @@
             TextNode("return;"),
         ],
         should_add_break=False)
-    for feature, interfaces in sorted(feature_to_interfaces.items()):
+    for feature, class_likes in sorted(feature_to_class_likes.items()):
         entries = [
             TextNode("{{"
                      "{0}::GetWrapperTypeInfo(), "
                      "{0}::InstallContextDependentProperties"
-                     "}}, ".format(v8_bridge_class_name(interface)))
-            for interface in sorted(interfaces, key=lambda x: x.identifier)
+                     "}}, ".format(v8_bridge_class_name(class_like)))
+            for class_like in sorted(class_likes, key=lambda x: x.identifier)
         ]
         table_def = ListNode([
             TextNode("static const std::pair<"
@@ -7225,8 +7257,8 @@
                  "(${script_state}, ${feature}, selected_wti_list);"),
     ])
 
-    for interface in set_of_interfaces:
-        path_manager = PathManager(interface)
+    for class_like in set_of_class_likes:
+        path_manager = PathManager(class_like)
         source_node.accumulator.add_include_headers(
             [path_manager.api_path(ext="h")])
 
@@ -7302,7 +7334,7 @@
         name=function_name, arg_decls=[], return_type="void")
     header_bindings_ns.body.extend([
         TextNode("""\
-// Initializes cross-component trampolines of IDL interface implementations.\
+// Initializes cross-component trampolines of IDL interface / namespace.\
 """),
         func_decl,
     ])
@@ -7330,16 +7362,17 @@
     ])
 
     init_calls = []
-    for interface in web_idl_database.interfaces:
-        if interface.code_generator_info.for_testing != for_testing:
+    for class_like in itertools.chain(web_idl_database.interfaces,
+                                      web_idl_database.namespaces):
+        if class_like.code_generator_info.for_testing != for_testing:
             continue
 
-        path_manager = PathManager(interface)
+        path_manager = PathManager(class_like)
         if path_manager.is_cross_components:
             source_node.accumulator.add_include_headers(
                 [path_manager.impl_path(ext="h")])
 
-            class_name = v8_bridge_class_name(interface)
+            class_name = v8_bridge_class_name(class_like)
             init_calls.append(_format("{}::Impl::Init();", class_name))
     for init_call in sorted(init_calls):
         func_def.body.append(TextNode(init_call))
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/namespace.py b/third_party/blink/renderer/bindings/scripts/bind_gen/namespace.py
new file mode 100644
index 0000000..247f5505
--- /dev/null
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/namespace.py
@@ -0,0 +1,30 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import web_idl
+
+from .package_initializer import package_initializer
+from .task_queue import TaskQueue
+
+# IDL interface and IDL namespace share a lot by their nature, so this module
+# uses the implementation of IDL interface.
+from .interface import generate_class_like
+
+
+def generate_namespace(namespace_identifier):
+    assert isinstance(namespace_identifier, web_idl.Identifier)
+
+    web_idl_database = package_initializer().web_idl_database()
+    namespace = web_idl_database.find(namespace_identifier)
+
+    generate_class_like(namespace)
+
+
+def generate_namespaces(task_queue):
+    assert isinstance(task_queue, TaskQueue)
+
+    web_idl_database = package_initializer().web_idl_database()
+
+    for namespace in web_idl_database.namespaces:
+        task_queue.post_task(generate_namespace, namespace.identifier)
diff --git a/third_party/blink/renderer/bindings/scripts/generate_bindings.py b/third_party/blink/renderer/bindings/scripts/generate_bindings.py
index 528d1b2..1e1cdb3 100644
--- a/third_party/blink/renderer/bindings/scripts/generate_bindings.py
+++ b/third_party/blink/renderer/bindings/scripts/generate_bindings.py
@@ -67,6 +67,7 @@
         'dictionary': bind_gen.generate_dictionaries,
         'enumeration': bind_gen.generate_enumerations,
         'interface': bind_gen.generate_interfaces,
+        'namespace': bind_gen.generate_namespaces,
     }
 
     for task in tasks:
diff --git a/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps b/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps
index 36dc292..0067285 100644
--- a/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps
+++ b/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps
@@ -41,6 +41,7 @@
 bind_gen/interface.py
 bind_gen/mako_renderer.py
 bind_gen/name_style.py
+bind_gen/namespace.py
 bind_gen/package_initializer.py
 bind_gen/path_manager.py
 bind_gen/style_format.py
diff --git a/third_party/blink/renderer/bindings/scripts/idl_definitions.py b/third_party/blink/renderer/bindings/scripts/idl_definitions.py
index 14e6e9d..0fc86d4 100644
--- a/third_party/blink/renderer/bindings/scripts/idl_definitions.py
+++ b/third_party/blink/renderer/bindings/scripts/idl_definitions.py
@@ -110,7 +110,7 @@
         children = node.GetChildren()
         for child in children:
             child_class = child.GetClass()
-            if child_class == 'Interface':
+            if child_class == 'Interface' or child_class == 'Namespace':
                 interface = IdlInterface(child)
                 self.interfaces[interface.name] = interface
                 if not self.first_name:
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 78a85db..0941392a 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -298,6 +298,7 @@
   allow_circular_includes_from = [
     ":core_generated",
     ":core_hot",
+    "//third_party/blink/renderer/core/probe",
     "//third_party/blink/renderer/core/xml:xpath_generated",
   ]
 
@@ -1111,6 +1112,9 @@
     "//v8",
   ]
 
+  allow_circular_includes_from =
+      [ "//third_party/blink/renderer/core/probe:probe" ]
+
   configs += [
     ":core_include_dirs",
     "//tools/v8_context_snapshot:use_v8_context_snapshot",
diff --git a/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc b/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc
index 060b3e9e..ff492266 100644
--- a/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc
+++ b/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc
@@ -21,8 +21,7 @@
       callback_collection_(context),
       context_(context) {}
 
-int WorkerAnimationFrameProvider::RegisterCallback(
-    FrameRequestCallbackCollection::FrameCallback* callback) {
+int WorkerAnimationFrameProvider::RegisterCallback(FrameCallback* callback) {
   if (!begin_frame_provider_->IsValidFrameProvider()) {
     return WorkerAnimationFrameProvider::kInvalidCallbackId;
   }
diff --git a/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h b/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h
index 9894003..bffb2db 100644
--- a/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h
+++ b/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h
@@ -34,7 +34,7 @@
       ExecutionContext* context,
       const BeginFrameProviderParams& begin_frame_provider_params);
 
-  int RegisterCallback(FrameRequestCallbackCollection::FrameCallback* callback);
+  int RegisterCallback(FrameCallback* callback);
   void CancelCallback(int id);
 
   void Trace(Visitor* visitor) const override;
diff --git a/third_party/blink/renderer/core/aom/computed_accessible_node.cc b/third_party/blink/renderer/core/aom/computed_accessible_node.cc
index b6a36be1..b3e92206 100644
--- a/third_party/blink/renderer/core/aom/computed_accessible_node.cc
+++ b/third_party/blink/renderer/core/aom/computed_accessible_node.cc
@@ -22,7 +22,7 @@
 namespace blink {
 
 class ComputedAccessibleNodePromiseResolver::RequestAnimationFrameCallback final
-    : public FrameRequestCallbackCollection::FrameCallback {
+    : public FrameCallback {
  public:
   explicit RequestAnimationFrameCallback(
       ComputedAccessibleNodePromiseResolver* resolver)
@@ -35,7 +35,7 @@
 
   void Trace(Visitor* visitor) const override {
     visitor->Trace(resolver_);
-    FrameRequestCallbackCollection::FrameCallback::Trace(visitor);
+    FrameCallback::Trace(visitor);
   }
 
  private:
diff --git a/third_party/blink/renderer/core/css/build.gni b/third_party/blink/renderer/core/css/build.gni
index f5726ac..41cf5d09 100644
--- a/third_party/blink/renderer/core/css/build.gni
+++ b/third_party/blink/renderer/core/css/build.gni
@@ -380,6 +380,8 @@
   "media_values_dynamic.h",
   "media_values_initial_viewport.cc",
   "media_values_initial_viewport.h",
+  "native_paint_image_generator.cc",
+  "native_paint_image_generator.h",
   "offscreen_font_selector.cc",
   "offscreen_font_selector.h",
   "page_rule_collector.cc",
diff --git a/third_party/blink/renderer/core/css/native_paint_image_generator.cc b/third_party/blink/renderer/core/css/native_paint_image_generator.cc
new file mode 100644
index 0000000..3390228
--- /dev/null
+++ b/third_party/blink/renderer/core/css/native_paint_image_generator.cc
@@ -0,0 +1,31 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/native_paint_image_generator.h"
+
+namespace blink {
+
+namespace {
+
+NativePaintImageGenerator::NativePaintImageGeneratorCreateFunction
+    g_create_function = nullptr;
+
+}  // namespace
+
+// static
+void NativePaintImageGenerator::Init(
+    NativePaintImageGeneratorCreateFunction create_function) {
+  DCHECK(!g_create_function);
+  g_create_function = create_function;
+}
+
+// static
+std::unique_ptr<NativePaintImageGenerator> NativePaintImageGenerator::Create() {
+  DCHECK(g_create_function);
+  return g_create_function();
+}
+
+NativePaintImageGenerator::~NativePaintImageGenerator() = default;
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/css/native_paint_image_generator.h b/third_party/blink/renderer/core/css/native_paint_image_generator.h
new file mode 100644
index 0000000..465f0549
--- /dev/null
+++ b/third_party/blink/renderer/core/css/native_paint_image_generator.h
@@ -0,0 +1,31 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_NATIVE_PAINT_IMAGE_GENERATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_NATIVE_PAINT_IMAGE_GENERATOR_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/geometry/float_size.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace blink {
+
+class Image;
+
+class CORE_EXPORT NativePaintImageGenerator {
+ public:
+  static std::unique_ptr<NativePaintImageGenerator> Create();
+  virtual ~NativePaintImageGenerator();
+
+  typedef std::unique_ptr<NativePaintImageGenerator> (
+      *NativePaintImageGeneratorCreateFunction)();
+  static void Init(NativePaintImageGeneratorCreateFunction);
+
+  virtual scoped_refptr<Image> Paint(const FloatSize& container_size,
+                                     SkColor color) = 0;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_NATIVE_PAINT_IMAGE_GENERATOR_H_
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index d233da31..87554717 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -144,6 +144,7 @@
 #include "third_party/blink/renderer/core/dom/node_with_index.h"
 #include "third_party/blink/renderer/core/dom/processing_instruction.h"
 #include "third_party/blink/renderer/core/dom/scripted_animation_controller.h"
+#include "third_party/blink/renderer/core/dom/scripted_idle_task_controller.h"
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
 #include "third_party/blink/renderer/core/dom/slot_assignment.h"
 #include "third_party/blink/renderer/core/dom/slot_assignment_engine.h"
@@ -7497,8 +7498,7 @@
   return *scripted_animation_controller_;
 }
 
-int Document::RequestAnimationFrame(
-    FrameRequestCallbackCollection::FrameCallback* callback) {
+int Document::RequestAnimationFrame(FrameCallback* callback) {
   return scripted_animation_controller_->RegisterFrameCallback(callback);
 }
 
@@ -7530,9 +7530,8 @@
   return *scripted_idle_task_controller_;
 }
 
-int Document::RequestIdleCallback(
-    ScriptedIdleTaskController::IdleTask* idle_task,
-    const IdleRequestOptions* options) {
+int Document::RequestIdleCallback(IdleTask* idle_task,
+                                  const IdleRequestOptions* options) {
   return EnsureScriptedIdleTaskController().RegisterCallback(idle_task,
                                                              options);
 }
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
index 06141f7c..c113ec3 100644
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -53,10 +53,8 @@
 #include "third_party/blink/renderer/core/dom/document_encoding_data.h"
 #include "third_party/blink/renderer/core/dom/document_lifecycle.h"
 #include "third_party/blink/renderer/core/dom/document_timing.h"
-#include "third_party/blink/renderer/core/dom/frame_request_callback_collection.h"
 #include "third_party/blink/renderer/core/dom/live_node_list_registry.h"
 #include "third_party/blink/renderer/core/dom/qualified_name.h"
-#include "third_party/blink/renderer/core/dom/scripted_idle_task_controller.h"
 #include "third_party/blink/renderer/core/dom/synchronous_mutation_observer.h"
 #include "third_party/blink/renderer/core/dom/text_link_colors.h"
 #include "third_party/blink/renderer/core/dom/tree_scope.h"
@@ -145,6 +143,7 @@
 class FloatRect;
 class FontMatchingMetrics;
 class FormController;
+class FrameCallback;
 class HTMLAllCollection;
 class HTMLBodyElement;
 class FrameScheduler;
@@ -160,6 +159,7 @@
 class HitTestRequest;
 class HttpRefreshScheduler;
 class IdleRequestOptions;
+class IdleTask;
 class IntersectionObserverController;
 class LayoutView;
 class LazyLoadImageObserver;
@@ -183,6 +183,7 @@
 class ResourceFetcher;
 class RootScrollerController;
 class ScriptValue;
+class ScriptedIdleTaskController;
 class SVGDocumentExtensions;
 class SVGUseElement;
 class Text;
@@ -1295,13 +1296,12 @@
 
   const DocumentTiming& GetTiming() const { return document_timing_; }
 
-  int RequestAnimationFrame(FrameRequestCallbackCollection::FrameCallback*);
+  int RequestAnimationFrame(FrameCallback*);
   void CancelAnimationFrame(int id);
   void ServiceScriptedAnimations(
       base::TimeTicks monotonic_animation_start_time);
 
-  int RequestIdleCallback(ScriptedIdleTaskController::IdleTask*,
-                          const IdleRequestOptions*);
+  int RequestIdleCallback(IdleTask*, const IdleRequestOptions*);
   void CancelIdleCallback(int id);
 
   ScriptedAnimationController& GetScriptedAnimationController();
diff --git a/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc b/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc
index b6724f0..3c593fc 100644
--- a/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc
+++ b/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc
@@ -102,18 +102,15 @@
   visitor->Trace(context_);
 }
 
-FrameRequestCallbackCollection::V8FrameCallback::V8FrameCallback(
-    V8FrameRequestCallback* callback)
+V8FrameCallback::V8FrameCallback(V8FrameRequestCallback* callback)
     : callback_(callback) {}
 
-void FrameRequestCallbackCollection::V8FrameCallback::Trace(
-    blink::Visitor* visitor) const {
+void V8FrameCallback::Trace(blink::Visitor* visitor) const {
   visitor->Trace(callback_);
-  FrameRequestCallbackCollection::FrameCallback::Trace(visitor);
+  FrameCallback::Trace(visitor);
 }
 
-void FrameRequestCallbackCollection::V8FrameCallback::Invoke(
-    double highResTime) {
+void V8FrameCallback::Invoke(double highResTime) {
   callback_->InvokeAndReportException(nullptr, highResTime);
 }
 
diff --git a/third_party/blink/renderer/core/dom/frame_request_callback_collection.h b/third_party/blink/renderer/core/dom/frame_request_callback_collection.h
index 02e0111..1123eec 100644
--- a/third_party/blink/renderer/core/dom/frame_request_callback_collection.h
+++ b/third_party/blink/renderer/core/dom/frame_request_callback_collection.h
@@ -16,6 +16,53 @@
 
 class ExecutionContext;
 
+// |FrameCallback| is an interface type which generalizes callbacks which are
+// invoked when a script-based animation needs to be resampled.
+class CORE_EXPORT FrameCallback : public GarbageCollected<FrameCallback>,
+                                  public NameClient {
+ public:
+  virtual void Trace(Visitor* visitor) const {}
+  const char* NameInHeapSnapshot() const override { return "FrameCallback"; }
+  virtual ~FrameCallback() = default;
+  virtual void Invoke(double) = 0;
+
+  int Id() const { return id_; }
+  bool IsCancelled() const { return is_cancelled_; }
+  bool GetUseLegacyTimeBase() const { return use_legacy_time_base_; }
+  void SetId(int id) { id_ = id; }
+  void SetIsCancelled(bool is_cancelled) { is_cancelled_ = is_cancelled; }
+  void SetUseLegacyTimeBase(bool use_legacy_time_base) {
+    use_legacy_time_base_ = use_legacy_time_base;
+  }
+
+  probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
+
+ protected:
+  FrameCallback() = default;
+
+ private:
+  int id_ = 0;
+  bool is_cancelled_ = false;
+  bool use_legacy_time_base_ = false;
+  probe::AsyncTaskId async_task_id_;
+};
+
+// |V8FrameCallback| is an adapter class for the conversion from
+// |V8FrameRequestCallback| to |Framecallback|.
+class CORE_EXPORT V8FrameCallback : public FrameCallback {
+ public:
+  void Trace(Visitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "V8FrameCallback"; }
+
+  explicit V8FrameCallback(V8FrameRequestCallback*);
+  ~V8FrameCallback() override = default;
+
+  void Invoke(double) override;
+
+ private:
+  Member<V8FrameRequestCallback> callback_;
+};
+
 class GC_PLUGIN_IGNORE("crbug.com/841830")
     CORE_EXPORT FrameRequestCallbackCollection final : public NameClient {
   DISALLOW_NEW();
@@ -25,55 +72,6 @@
 
   using CallbackId = int;
 
-  // |FrameCallback| is an interface type which generalizes callbacks which are
-  // invoked when a script-based animation needs to be resampled.
-  class CORE_EXPORT FrameCallback : public GarbageCollected<FrameCallback>,
-                                    public NameClient {
-   public:
-    virtual void Trace(Visitor* visitor) const {}
-    const char* NameInHeapSnapshot() const override { return "FrameCallback"; }
-    virtual ~FrameCallback() = default;
-    virtual void Invoke(double) = 0;
-
-    int Id() const { return id_; }
-    bool IsCancelled() const { return is_cancelled_; }
-    bool GetUseLegacyTimeBase() const { return use_legacy_time_base_; }
-    void SetId(int id) { id_ = id; }
-    void SetIsCancelled(bool is_cancelled) { is_cancelled_ = is_cancelled; }
-    void SetUseLegacyTimeBase(bool use_legacy_time_base) {
-      use_legacy_time_base_ = use_legacy_time_base;
-    }
-
-    probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
-
-   protected:
-    FrameCallback() = default;
-
-   private:
-    int id_ = 0;
-    bool is_cancelled_ = false;
-    bool use_legacy_time_base_ = false;
-    probe::AsyncTaskId async_task_id_;
-  };
-
-  // |V8FrameCallback| is an adapter class for the conversion from
-  // |V8FrameRequestCallback| to |Framecallback|.
-  class CORE_EXPORT V8FrameCallback : public FrameCallback {
-   public:
-    void Trace(Visitor*) const override;
-    const char* NameInHeapSnapshot() const override {
-      return "V8FrameCallback";
-    }
-
-    explicit V8FrameCallback(V8FrameRequestCallback*);
-    ~V8FrameCallback() override = default;
-
-    void Invoke(double) override;
-
-   private:
-    Member<V8FrameRequestCallback> callback_;
-  };
-
   CallbackId RegisterFrameCallback(FrameCallback*);
   void CancelFrameCallback(CallbackId);
   void ExecuteFrameCallbacks(double high_res_now_ms,
diff --git a/third_party/blink/renderer/core/dom/idle_deadline_test.cc b/third_party/blink/renderer/core/dom/idle_deadline_test.cc
index 2405410..c3dbf36b 100644
--- a/third_party/blink/renderer/core/dom/idle_deadline_test.cc
+++ b/third_party/blink/renderer/core/dom/idle_deadline_test.cc
@@ -41,10 +41,6 @@
     NOTREACHED();
     return nullptr;
   }
-  std::unique_ptr<PageScheduler> CreatePageScheduler(
-      PageScheduler::Delegate*) override {
-    return nullptr;
-  }
   scheduler::WebAgentGroupScheduler* GetCurrentAgentGroupScheduler() override {
     return nullptr;
   }
diff --git a/third_party/blink/renderer/core/dom/scripted_animation_controller.cc b/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
index 78c2ab1..3f909b3 100644
--- a/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
+++ b/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
@@ -91,8 +91,7 @@
 }
 
 ScriptedAnimationController::CallbackId
-ScriptedAnimationController::RegisterFrameCallback(
-    FrameRequestCallbackCollection::FrameCallback* callback) {
+ScriptedAnimationController::RegisterFrameCallback(FrameCallback* callback) {
   CallbackId id = callback_collection_.RegisterFrameCallback(callback);
   ScheduleAnimationIfNeeded();
   return id;
diff --git a/third_party/blink/renderer/core/dom/scripted_animation_controller.h b/third_party/blink/renderer/core/dom/scripted_animation_controller.h
index 58cea43..7f55d6b6 100644
--- a/third_party/blink/renderer/core/dom/scripted_animation_controller.h
+++ b/third_party/blink/renderer/core/dom/scripted_animation_controller.h
@@ -65,8 +65,7 @@
 
   // Animation frame callbacks are used for requestAnimationFrame().
   typedef int CallbackId;
-  CallbackId RegisterFrameCallback(
-      FrameRequestCallbackCollection::FrameCallback*);
+  CallbackId RegisterFrameCallback(FrameCallback*);
   void CancelFrameCallback(CallbackId);
   // Returns true if any callback is currently registered.
   bool HasFrameCallback() const;
diff --git a/third_party/blink/renderer/core/dom/scripted_animation_controller_test.cc b/third_party/blink/renderer/core/dom/scripted_animation_controller_test.cc
index fb3344ca..1539108 100644
--- a/third_party/blink/renderer/core/dom/scripted_animation_controller_test.cc
+++ b/third_party/blink/renderer/core/dom/scripted_animation_controller_test.cc
@@ -155,8 +155,7 @@
 
 namespace {
 
-class RunTaskCallback final
-    : public FrameRequestCallbackCollection::FrameCallback {
+class RunTaskCallback final : public FrameCallback {
  public:
   RunTaskCallback(base::RepeatingClosure task) : task_(std::move(task)) {}
   void Invoke(double) override { task_.Run(); }
diff --git a/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc b/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc
index c7141f3..d280bbb 100644
--- a/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc
+++ b/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc
@@ -74,16 +74,14 @@
 
 }  // namespace internal
 
-ScriptedIdleTaskController::V8IdleTask::V8IdleTask(
-    V8IdleRequestCallback* callback)
-    : callback_(callback) {}
+V8IdleTask::V8IdleTask(V8IdleRequestCallback* callback) : callback_(callback) {}
 
-void ScriptedIdleTaskController::V8IdleTask::Trace(Visitor* visitor) const {
+void V8IdleTask::Trace(Visitor* visitor) const {
   visitor->Trace(callback_);
-  ScriptedIdleTaskController::IdleTask::Trace(visitor);
+  IdleTask::Trace(visitor);
 }
 
-void ScriptedIdleTaskController::V8IdleTask::invoke(IdleDeadline* deadline) {
+void V8IdleTask::invoke(IdleDeadline* deadline) {
   callback_->InvokeAndReportException(nullptr, deadline);
 }
 
diff --git a/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h b/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h
index 279d0807..4c36b6b 100644
--- a/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h
+++ b/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h
@@ -23,6 +23,38 @@
 class IdleRequestOptions;
 class ThreadScheduler;
 
+// |IdleTask| is an interface type which generalizes tasks which are invoked
+// on idle. The tasks need to define what to do on idle in |invoke|.
+class IdleTask : public GarbageCollected<IdleTask>, public NameClient {
+ public:
+  virtual void Trace(Visitor* visitor) const {}
+  const char* NameInHeapSnapshot() const override { return "IdleTask"; }
+  virtual ~IdleTask() = default;
+  virtual void invoke(IdleDeadline*) = 0;
+  probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
+
+ private:
+  probe::AsyncTaskId async_task_id_;
+};
+
+// |V8IdleTask| is the adapter class for the conversion from
+// |V8IdleRequestCallback| to |IdleTask|.
+class V8IdleTask : public IdleTask {
+ public:
+  static V8IdleTask* Create(V8IdleRequestCallback* callback) {
+    return MakeGarbageCollected<V8IdleTask>(callback);
+  }
+
+  explicit V8IdleTask(V8IdleRequestCallback*);
+  ~V8IdleTask() override = default;
+
+  void invoke(IdleDeadline*) override;
+  void Trace(Visitor*) const override;
+
+ private:
+  Member<V8IdleRequestCallback> callback_;
+};
+
 class CORE_EXPORT ScriptedIdleTaskController
     : public GarbageCollected<ScriptedIdleTaskController>,
       public ExecutionContextLifecycleStateObserver,
@@ -45,38 +77,6 @@
 
   using CallbackId = int;
 
-  // |IdleTask| is an interface type which generalizes tasks which are invoked
-  // on idle. The tasks need to define what to do on idle in |invoke|.
-  class IdleTask : public GarbageCollected<IdleTask>, public NameClient {
-   public:
-    virtual void Trace(Visitor* visitor) const {}
-    const char* NameInHeapSnapshot() const override { return "IdleTask"; }
-    virtual ~IdleTask() = default;
-    virtual void invoke(IdleDeadline*) = 0;
-    probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
-
-   private:
-    probe::AsyncTaskId async_task_id_;
-  };
-
-  // |V8IdleTask| is the adapter class for the conversion from
-  // |V8IdleRequestCallback| to |IdleTask|.
-  class V8IdleTask : public IdleTask {
-   public:
-    static V8IdleTask* Create(V8IdleRequestCallback* callback) {
-      return MakeGarbageCollected<V8IdleTask>(callback);
-    }
-
-    explicit V8IdleTask(V8IdleRequestCallback*);
-    ~V8IdleTask() override = default;
-
-    void invoke(IdleDeadline*) override;
-    void Trace(Visitor*) const override;
-
-   private:
-    Member<V8IdleRequestCallback> callback_;
-  };
-
   int RegisterCallback(IdleTask*, const IdleRequestOptions*);
   void CancelCallback(CallbackId);
 
diff --git a/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc b/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
index b68445a..9e04ad7 100644
--- a/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
+++ b/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
@@ -63,10 +63,6 @@
     NOTREACHED();
     return nullptr;
   }
-  std::unique_ptr<PageScheduler> CreatePageScheduler(
-      PageScheduler::Delegate*) override {
-    return nullptr;
-  }
   std::unique_ptr<RendererPauseHandle> PauseScheduler() override {
     return nullptr;
   }
@@ -106,7 +102,7 @@
       base::MakeRefCounted<scheduler::FakeTaskRunner>();
 };
 
-class MockIdleTask : public ScriptedIdleTaskController::IdleTask {
+class MockIdleTask : public IdleTask {
  public:
   MOCK_METHOD1(invoke, void(IdleDeadline*));
 };
diff --git a/third_party/blink/renderer/core/editing/selection_controller.h b/third_party/blink/renderer/core/editing/selection_controller.h
index 1188d6f..b514f295 100644
--- a/third_party/blink/renderer/core/editing/selection_controller.h
+++ b/third_party/blink/renderer/core/editing/selection_controller.h
@@ -33,6 +33,7 @@
 #include "third_party/blink/renderer/core/editing/frame_selection.h"
 #include "third_party/blink/renderer/core/editing/position_with_affinity.h"
 #include "third_party/blink/renderer/core/editing/text_granularity.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/page/event_with_hit_test_results.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
diff --git a/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc b/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
index 40f70b0d..6c8f07989 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
+++ b/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
@@ -41,15 +41,14 @@
 
 }  // namespace
 
-class IdleSpellCheckController::IdleCallback final
-    : public ScriptedIdleTaskController::IdleTask {
+class IdleSpellCheckController::IdleCallback final : public IdleTask {
  public:
   explicit IdleCallback(IdleSpellCheckController* controller)
       : controller_(controller) {}
 
   void Trace(Visitor* visitor) const final {
     visitor->Trace(controller_);
-    ScriptedIdleTaskController::IdleTask::Trace(visitor);
+    IdleTask::Trace(visitor);
   }
 
  private:
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index 02774a9c..9f707a0 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -391,13 +391,14 @@
     bool compositing_enabled,
     WebView* opener,
     CrossVariantMojoAssociatedReceiver<mojom::PageBroadcastInterfaceBase>
-        page_handle) {
+        page_handle,
+    scheduler::WebAgentGroupScheduler& agent_group_scheduler) {
   return WebViewImpl::Create(
       client,
       is_hidden ? mojom::blink::PageVisibilityState::kHidden
                 : mojom::blink::PageVisibilityState::kVisible,
       is_inside_portal, compositing_enabled, static_cast<WebViewImpl*>(opener),
-      std::move(page_handle));
+      std::move(page_handle), agent_group_scheduler);
 }
 
 WebViewImpl* WebViewImpl::Create(
@@ -406,12 +407,13 @@
     bool is_inside_portal,
     bool compositing_enabled,
     WebViewImpl* opener,
-    mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle) {
+    mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle,
+    blink::scheduler::WebAgentGroupScheduler& agent_group_scheduler) {
   // Take a self-reference for WebViewImpl that is released by calling Close(),
   // then return a raw pointer to the caller.
   auto web_view = base::AdoptRef(
       new WebViewImpl(client, visibility, is_inside_portal, compositing_enabled,
-                      opener, std::move(page_handle)));
+                      opener, std::move(page_handle), agent_group_scheduler));
   web_view->AddRef();
   return web_view.get();
 }
@@ -464,7 +466,8 @@
     bool is_inside_portal,
     bool does_composite,
     WebViewImpl* opener,
-    mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle)
+    mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle,
+    blink::scheduler::WebAgentGroupScheduler& agent_group_scheduler)
     : web_view_client_(client),
       chrome_client_(MakeGarbageCollected<ChromeClientImpl>(this)),
       minimum_zoom_level_(PageZoomFactorToZoomLevel(kMinimumPageZoomFactor)),
@@ -477,7 +480,8 @@
   Page::PageClients page_clients;
   page_clients.chrome_client = chrome_client_.Get();
   page_ =
-      Page::CreateOrdinary(page_clients, opener ? opener->GetPage() : nullptr);
+      Page::CreateOrdinary(page_clients, opener ? opener->GetPage() : nullptr,
+                           agent_group_scheduler);
   CoreInitializer::GetInstance().ProvideModulesToPage(*page_, web_view_client_);
 
   SetVisibilityState(visibility, /*is_initial_state=*/true);
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h
index 33f24793..7ba87d7c 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.h
+++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -44,6 +44,7 @@
 #include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/page/page.mojom-blink.h"
 #include "third_party/blink/public/mojom/page/page_visibility_state.mojom-blink.h"
+#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
 #include "third_party/blink/public/platform/web_input_event_result.h"
 #include "third_party/blink/public/platform/web_rect.h"
 #include "third_party/blink/public/platform/web_string.h"
@@ -116,7 +117,8 @@
       bool is_inside_portal,
       bool compositing_enabled,
       WebViewImpl* opener,
-      mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle);
+      mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle,
+      scheduler::WebAgentGroupScheduler& agent_group_scheduler);
 
   // All calls to Create() should be balanced with a call to Close(). This
   // synchronously destroys the WebViewImpl.
@@ -580,7 +582,8 @@
       bool is_inside_portal,
       bool does_composite,
       WebViewImpl* opener,
-      mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle);
+      mojo::PendingAssociatedReceiver<mojom::blink::PageBroadcast> page_handle,
+      scheduler::WebAgentGroupScheduler& agent_group_scheduler);
   ~WebViewImpl() override;
 
   HitTestResult HitTestResultForRootFramePos(const FloatPoint&);
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc
index 2d1ca3a..5d991c8 100644
--- a/third_party/blink/renderer/core/exported/web_view_test.cc
+++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -62,6 +62,7 @@
 #include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
 #include "third_party/blink/public/mojom/input/touch_event.mojom-blink.h"
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/public/platform/web_drag_data.h"
 #include "third_party/blink/public/platform/web_size.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
@@ -503,9 +504,17 @@
   // initialization code between WebView and WebLocalFrame creation.
   frame_test_helpers::TestWebViewClient web_view_client;
   frame_test_helpers::TestWebWidgetClient web_widget_client;
-  WebViewImpl* web_view = static_cast<WebViewImpl*>(WebView::Create(
-      &web_view_client, /*is_hidden=*/false, /*is_inside_portal=*/false,
-      /*compositing_enabled=*/true, nullptr, mojo::NullAssociatedReceiver()));
+  std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+      agent_group_scheduler =
+          blink::scheduler::WebThreadScheduler::MainThreadScheduler()
+              ->CreateAgentGroupScheduler();
+  WebViewImpl* web_view = static_cast<WebViewImpl*>(
+      WebView::Create(&web_view_client,
+                      /*is_hidden=*/false,
+                      /*is_inside_portal=*/false,
+                      /*compositing_enabled=*/true,
+                      /*opener=*/nullptr, mojo::NullAssociatedReceiver(),
+                      *agent_group_scheduler));
 
   EXPECT_NE(SK_ColorBLUE, web_view->BackgroundColor());
   // WebView does not have a frame yet, but we should still be able to set the
@@ -2735,9 +2744,14 @@
 TEST_F(WebViewTest, ClientTapHandlingNullWebViewClient) {
   // Note: this test doesn't use WebViewHelper since WebViewHelper creates an
   // internal WebViewClient on demand if the supplied WebViewClient is null.
+  std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+      agent_group_scheduler =
+          blink::scheduler::WebThreadScheduler::MainThreadScheduler()
+              ->CreateAgentGroupScheduler();
   WebViewImpl* web_view = static_cast<WebViewImpl*>(WebView::Create(
-      nullptr, false, /*is_inside_portal=*/false,
-      /*compositing_enabled=*/false, nullptr, mojo::NullAssociatedReceiver()));
+      /*client=*/nullptr, /*is_hidden=*/false, /*is_inside_portal=*/false,
+      /*compositing_enabled=*/false, /*opener=*/nullptr,
+      mojo::NullAssociatedReceiver(), *agent_group_scheduler));
   frame_test_helpers::TestWebFrameClient web_frame_client;
   frame_test_helpers::TestWebWidgetClient web_widget_client;
   WebLocalFrame* local_frame =
@@ -4188,9 +4202,14 @@
   // initialization code between WebView and WebLocalFrame creation.
   frame_test_helpers::TestWebViewClient web_view_client;
   frame_test_helpers::TestWebWidgetClient web_widget_client;
+  std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+      agent_group_scheduler =
+          blink::scheduler::WebThreadScheduler::MainThreadScheduler()
+              ->CreateAgentGroupScheduler();
   WebViewImpl* web_view_impl = static_cast<WebViewImpl*>(WebView::Create(
-      &web_view_client, /*is_hidden*/ false, /*is_inside_portal=*/false,
-      /*compositing_enabled=*/true, nullptr, mojo::NullAssociatedReceiver()));
+      &web_view_client, /*is_hidden=*/false, /*is_inside_portal=*/false,
+      /*compositing_enabled=*/true, /*opener=*/nullptr,
+      mojo::NullAssociatedReceiver(), *agent_group_scheduler));
 
   frame_test_helpers::TestWebFrameClient web_frame_client;
   WebLocalFrame* frame =
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
index 96a6c94..4528efe 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -1451,21 +1451,10 @@
           mojom::blink::InspectorIssueCode::kContentSecurityPolicyIssue,
           std::move(details));
 
-  // TODO(crbug.com/1082628): Add handling of other CSP violation types later as
-  // they'll need more work.
-  if (violation_type == blink::ContentSecurityPolicy::
-                            ContentSecurityPolicyViolationType::kURLViolation ||
-      violation_type ==
-          blink::ContentSecurityPolicy::ContentSecurityPolicyViolationType::
-              kInlineViolation ||
-      violation_type ==
-          blink::ContentSecurityPolicy::ContentSecurityPolicyViolationType::
-              kEvalViolation) {
-    if (frame_ancestor)
-      frame_ancestor->AddInspectorIssue(std::move(info));
-    else if (delegate_)
-      delegate_->AddInspectorIssue(std::move(info));
-  }
+  if (frame_ancestor)
+    frame_ancestor->AddInspectorIssue(std::move(info));
+  else if (delegate_)
+    delegate_->AddInspectorIssue(std::move(info));
 }
 
 void ContentSecurityPolicy::LogToConsole(ConsoleMessage* console_message,
diff --git a/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc b/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc
index 2a8f4bc..f718f51a 100644
--- a/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc
+++ b/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc
@@ -296,8 +296,7 @@
 
 namespace {
 
-class CheckRafCallback final
-    : public FrameRequestCallbackCollection::FrameCallback {
+class CheckRafCallback final : public FrameCallback {
  public:
   void Invoke(double high_res_time_ms) override { was_called_ = true; }
   bool WasCalled() const { return was_called_; }
diff --git a/third_party/blink/renderer/core/frame/frame_overlay_test.cc b/third_party/blink/renderer/core/frame/frame_overlay_test.cc
index db1d542..0ddaf46 100644
--- a/third_party/blink/renderer/core/frame/frame_overlay_test.cc
+++ b/third_party/blink/renderer/core/frame/frame_overlay_test.cc
@@ -117,9 +117,9 @@
     graphics_layer->PaintRecursively(builder.Context(), pre_composited_layers);
     ASSERT_EQ(1u, pre_composited_layers.size());
     graphics_layer->GetPaintController().FinishCycle();
-    SkiaPaintCanvas paint_canvas(&canvas);
-    graphics_layer->GetPaintController().GetPaintArtifact().Replay(
-        paint_canvas, PropertyTreeState::Root());
+    SkiaPaintCanvas(&canvas).drawPicture(
+        graphics_layer->GetPaintController().GetPaintArtifact().GetPaintRecord(
+            PropertyTreeState::Root()));
   }
 }
 
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index f0bcfc4f..881d779 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -48,6 +48,7 @@
 #include "third_party/blink/public/mojom/page/widget.mojom-blink.h"
 #include "third_party/blink/public/platform/interface_registry.h"
 #include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/public/platform/web_data.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
@@ -401,7 +402,10 @@
 }
 
 WebViewHelper::WebViewHelper()
-    : web_view_(nullptr), platform_(Platform::Current()) {}
+    : web_view_(nullptr),
+      agent_group_scheduler_(
+          blink::ThreadScheduler::Current()->CreateAgentGroupScheduler()),
+      platform_(Platform::Current()) {}
 
 WebViewHelper::~WebViewHelper() {
   // Close the WebViewImpl before the WebViewClient/WebWidgetClient are
@@ -583,11 +587,13 @@
                                       class WebView* opener) {
   test_web_view_client_ =
       CreateDefaultClientIfNeeded(web_view_client, owned_test_web_view_client_);
-  web_view_ = static_cast<WebViewImpl*>(WebView::Create(
-      test_web_view_client_,
-      /*is_hidden=*/false,
-      /*is_inside_portal=*/false,
-      /*compositing_enabled=*/true, opener, mojo::NullAssociatedReceiver()));
+  web_view_ = static_cast<WebViewImpl*>(
+      WebView::Create(test_web_view_client_,
+                      /*is_hidden=*/false,
+                      /*is_inside_portal=*/false,
+                      /*compositing_enabled=*/true,
+                      /*opener=*/opener, mojo::NullAssociatedReceiver(),
+                      *agent_group_scheduler_));
   // This property must be set at initialization time, it is not supported to be
   // changed afterward, and does nothing.
   web_view_->GetSettings()->SetViewportEnabled(viewport_enabled_);
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.h b/third_party/blink/renderer/core/frame/frame_test_helpers.h
index 4400f44..20e9b6f 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.h
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -406,6 +406,9 @@
   std::unique_ptr<TestWebWidgetClient> owned_test_web_widget_client_;
   TestWebWidgetClient* test_web_widget_client_ = nullptr;
 
+  std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+      agent_group_scheduler_;
+
   // The Platform should not change during the lifetime of the test!
   Platform* const platform_;
 
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index 2e01ca45..7f3ef29 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -1665,9 +1665,7 @@
 
 int LocalDOMWindow::requestAnimationFrame(V8FrameRequestCallback* callback) {
   if (Document* doc = document()) {
-    auto* frame_callback =
-        MakeGarbageCollected<FrameRequestCallbackCollection::V8FrameCallback>(
-            callback);
+    auto* frame_callback = MakeGarbageCollected<V8FrameCallback>(callback);
     frame_callback->SetUseLegacyTimeBase(false);
     return doc->RequestAnimationFrame(frame_callback);
   }
@@ -1677,9 +1675,7 @@
 int LocalDOMWindow::webkitRequestAnimationFrame(
     V8FrameRequestCallback* callback) {
   if (Document* doc = document()) {
-    auto* frame_callback =
-        MakeGarbageCollected<FrameRequestCallbackCollection::V8FrameCallback>(
-            callback);
+    auto* frame_callback = MakeGarbageCollected<V8FrameCallback>(callback);
     frame_callback->SetUseLegacyTimeBase(true);
     return doc->RequestAnimationFrame(frame_callback);
   }
@@ -1713,8 +1709,7 @@
                                         const IdleRequestOptions* options) {
   if (!GetFrame())
     return 0;
-  return document_->RequestIdleCallback(
-      ScriptedIdleTaskController::V8IdleTask::Create(callback), options);
+  return document_->RequestIdleCallback(V8IdleTask::Create(callback), options);
 }
 
 void LocalDOMWindow::cancelIdleCallback(int id) {
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
index fb6c8f3..b06fc2e0 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
@@ -166,6 +166,7 @@
         widget_host,
     CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
         widget,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     bool hidden,
     bool never_composited,
     bool is_for_child_local_root)
@@ -176,11 +177,9 @@
                                                 never_composited,
                                                 is_for_child_local_root)),
       client_(&client) {
-  frame_widget_host_.Bind(
-      std::move(frame_widget_host),
-      ThreadScheduler::Current()->DeprecatedDefaultTaskRunner());
-  receiver_.Bind(std::move(frame_widget),
-                 ThreadScheduler::Current()->DeprecatedDefaultTaskRunner());
+  DCHECK(task_runner);
+  frame_widget_host_.Bind(std::move(frame_widget_host), task_runner);
+  receiver_.Bind(std::move(frame_widget), task_runner);
 }
 
 WebFrameWidgetBase::~WebFrameWidgetBase() {
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.h b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
index 0e07a33..a38820f 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_base.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
@@ -75,6 +75,7 @@
           widget_host,
       CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
           widget,
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
       bool hidden,
       bool never_composited,
       bool is_for_child_local_root);
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index cb43a7e..2dedc92 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -85,6 +85,7 @@
 #include "third_party/blink/renderer/platform/graphics/color.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/keyboard_codes.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
 #include "third_party/blink/renderer/platform/widget/widget_base.h"
 
 namespace blink {
@@ -146,6 +147,7 @@
         util::PassKey<WebFrameWidget>(), *client, web_view_impl,
         std::move(mojo_frame_widget_host), std::move(mojo_frame_widget),
         std::move(mojo_widget_host), std::move(mojo_widget),
+        main_frame->Scheduler()->GetAgentGroupScheduler()->DefaultTaskRunner(),
         is_for_nested_main_frame, hidden, never_composited);
   } else {
     // Note: this isn't a leak, as the object has a self-reference that the
@@ -155,6 +157,7 @@
         util::PassKey<WebFrameWidget>(), *client, web_view_impl,
         std::move(mojo_frame_widget_host), std::move(mojo_frame_widget),
         std::move(mojo_widget_host), std::move(mojo_widget),
+        main_frame->Scheduler()->GetAgentGroupScheduler()->DefaultTaskRunner(),
         is_for_nested_main_frame, hidden, never_composited);
   }
   widget->BindLocalRoot(*main_frame);
@@ -186,8 +189,9 @@
   auto* widget = MakeGarbageCollected<WebFrameWidgetImpl>(
       util::PassKey<WebFrameWidget>(), *client,
       std::move(mojo_frame_widget_host), std::move(mojo_frame_widget),
-      std::move(mojo_widget_host), std::move(mojo_widget), hidden,
-      never_composited);
+      std::move(mojo_widget_host), std::move(mojo_widget),
+      local_root->Scheduler()->GetAgentGroupScheduler()->DefaultTaskRunner(),
+      hidden, never_composited);
   widget->BindLocalRoot(*local_root);
   return widget;
 }
@@ -203,6 +207,7 @@
         widget_host,
     CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
         widget,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     bool hidden,
     bool never_composited)
     : WebFrameWidgetBase(client,
@@ -210,6 +215,7 @@
                          std::move(frame_widget),
                          std::move(widget_host),
                          std::move(widget),
+                         std::move(task_runner),
                          hidden,
                          never_composited,
                          /*is_for_child_local_root=*/true),
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
index 5d9bfb2..606cec4 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -86,6 +86,7 @@
           widget_host,
       CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
           widget,
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
       bool hidden,
       bool never_composited);
   ~WebFrameWidgetImpl() override;
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_test.cc b/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
index 9353e16..360b852 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
@@ -232,13 +232,15 @@
     CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase>
         widget_host,
     CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase> widget,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     bool is_for_nested_main_frame,
     bool hidden,
     bool never_composited) {
   return MakeGarbageCollected<MockWebViewFrameWidget>(
       pass_key, client, web_view_impl, std::move(frame_widget_host),
       std::move(frame_widget), std::move(widget_host), std::move(widget),
-      is_for_nested_main_frame, hidden, never_composited);
+      std::move(task_runner), is_for_nested_main_frame, hidden,
+      never_composited);
 }
 
 class WebViewFrameWidgetSimTest : public SimTest {
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index b1185d28..99a9339 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -2432,6 +2432,11 @@
   return GetFrame()->GetFrameScheduler();
 }
 
+scheduler::WebAgentGroupScheduler* WebLocalFrameImpl::GetAgentGroupScheduler()
+    const {
+  return Scheduler()->GetAgentGroupScheduler();
+}
+
 scoped_refptr<base::SingleThreadTaskRunner> WebLocalFrameImpl::GetTaskRunner(
     TaskType task_type) {
   return GetFrame()->GetTaskRunner(task_type);
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index 6f00bafc..0beff118 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -267,6 +267,7 @@
   void UsageCountChromeLoadTimes(const WebString& metric) override;
   bool DispatchedPagehideAndStillHidden() const override;
   FrameScheduler* Scheduler() const override;
+  scheduler::WebAgentGroupScheduler* GetAgentGroupScheduler() const override;
   scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
   WebInputMethodController* GetInputMethodController() override;
   WebAssociatedURLLoader* CreateAssociatedURLLoader(
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
index 12614f1..f477d60 100644
--- a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
+++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -30,6 +30,7 @@
         widget_host,
     CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
         widget,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     bool is_for_nested_main_frame,
     bool hidden,
     bool never_composited)
@@ -38,6 +39,7 @@
                          std::move(frame_widget),
                          std::move(widget_host),
                          std::move(widget),
+                         task_runner,
                          hidden,
                          never_composited,
                          /*is_for_child_local_root=*/false),
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.h b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
index a109cead..934d089 100644
--- a/third_party/blink/renderer/core/frame/web_view_frame_widget.h
+++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
@@ -51,6 +51,7 @@
           widget_host,
       CrossVariantMojoAssociatedReceiver<mojom::blink::WidgetInterfaceBase>
           widget,
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
       bool is_for_nested_main_frame,
       bool hidden,
       bool never_composited);
@@ -233,6 +234,8 @@
                                 widget_host,
                             CrossVariantMojoAssociatedReceiver<
                                 mojom::blink::WidgetInterfaceBase> widget,
+                            scoped_refptr<base::SingleThreadTaskRunner>
+                                task_runner,
                             bool is_for_nested_main_frame,
                             bool hidden,
                             bool never_composited);
diff --git a/third_party/blink/renderer/core/html/html_marquee_element.cc b/third_party/blink/renderer/core/html/html_marquee_element.cc
index 4f85043..6cbe378 100644
--- a/third_party/blink/renderer/core/html/html_marquee_element.cc
+++ b/third_party/blink/renderer/core/html/html_marquee_element.cc
@@ -78,7 +78,7 @@
 }
 
 class HTMLMarqueeElement::RequestAnimationFrameCallback final
-    : public FrameRequestCallbackCollection::FrameCallback {
+    : public FrameCallback {
  public:
   explicit RequestAnimationFrameCallback(HTMLMarqueeElement* marquee)
       : marquee_(marquee) {}
@@ -90,7 +90,7 @@
 
   void Trace(Visitor* visitor) const override {
     visitor->Trace(marquee_);
-    FrameRequestCallbackCollection::FrameCallback::Trace(visitor);
+    FrameCallback::Trace(visitor);
   }
 
  private:
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc
index c3786c7..1252339 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc
@@ -120,7 +120,7 @@
   const ComputedStyle& block_style = fragment.Style();
   bool should_align_caret_right =
       ShouldAlignCaretRight(block_style.GetTextAlign(is_last_line),
-                            block_style.Direction()) &&
+                            line_box.Current().BaseDirection()) &&
       (style.GetUnicodeBidi() != UnicodeBidi::kPlaintext ||
        IsLtr(cursor.Current().ResolvedDirection()));
 
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc
index a5668d9..a5556215 100644
--- a/third_party/blink/renderer/core/page/page.cc
+++ b/third_party/blink/renderer/core/page/page.cc
@@ -89,6 +89,7 @@
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
+#include "third_party/blink/renderer/platform/scheduler/public/agent_group_scheduler.h"
 #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
 #include "third_party/skia/include/core/SkColor.h"
 
@@ -160,15 +161,23 @@
 
 Page* Page::CreateNonOrdinary(PageClients& page_clients) {
   Page* page = MakeGarbageCollected<Page>(page_clients);
-  page->SetPageScheduler(ThreadScheduler::Current()->CreatePageScheduler(page));
+  std::unique_ptr<scheduler::WebAgentGroupScheduler> agent_group_scheduler =
+      ThreadScheduler::Current()->CreateAgentGroupScheduler();
+  page->SetPageScheduler(
+      agent_group_scheduler->AsAgentGroupScheduler().CreatePageScheduler(page));
+  page->SetAgentGroupSchedulerForNonOrdinary(std::move(agent_group_scheduler));
   return page;
 }
 
-Page* Page::CreateOrdinary(PageClients& page_clients, Page* opener) {
+Page* Page::CreateOrdinary(
+    PageClients& page_clients,
+    Page* opener,
+    scheduler::WebAgentGroupScheduler& agent_group_scheduler) {
   Page* page = MakeGarbageCollected<Page>(page_clients);
   page->is_ordinary_ = true;
   page->agent_metrics_collector_ = &GlobalAgentMetricsCollector();
-  page->SetPageScheduler(ThreadScheduler::Current()->CreatePageScheduler(page));
+  page->SetPageScheduler(
+      agent_group_scheduler.AsAgentGroupScheduler().CreatePageScheduler(page));
 
   if (opener) {
     // Before: ... -> opener -> next -> ...
@@ -977,7 +986,8 @@
       });
   page_visibility_observer_set_.Clear();
 
-  page_scheduler_.reset();
+  page_scheduler_ = nullptr;
+  agent_group_scheduler_for_non_ordinary_ = nullptr;
 }
 
 void Page::RegisterPluginsChangedObserver(PluginsChangedObserver* observer) {
@@ -994,6 +1004,12 @@
   return page_scheduler_.get();
 }
 
+void Page::SetAgentGroupSchedulerForNonOrdinary(
+    std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+        agent_group_scheduler) {
+  agent_group_scheduler_for_non_ordinary_ = std::move(agent_group_scheduler);
+}
+
 void Page::SetPageScheduler(std::unique_ptr<PageScheduler> page_scheduler) {
   page_scheduler_ = std::move(page_scheduler);
   // The scheduler should be set before the main frame.
diff --git a/third_party/blink/renderer/core/page/page.h b/third_party/blink/renderer/core/page/page.h
index c184b1fd..65b72a9 100644
--- a/third_party/blink/renderer/core/page/page.h
+++ b/third_party/blink/renderer/core/page/page.h
@@ -30,6 +30,7 @@
 #include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
 #include "third_party/blink/public/mojom/page/page.mojom-blink.h"
 #include "third_party/blink/public/mojom/page/page_visibility_state.mojom-blink.h"
+#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
 #include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
 #include "third_party/blink/public/web/web_window_features.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -117,7 +118,10 @@
   static Page* CreateNonOrdinary(PageClients& pages_clients);
 
   // An "ordinary" page is a fully-featured page owned by a web view.
-  static Page* CreateOrdinary(PageClients&, Page* opener);
+  static Page* CreateOrdinary(
+      PageClients&,
+      Page* opener,
+      scheduler::WebAgentGroupScheduler& agent_group_scheduler);
 
   explicit Page(PageClients&);
   ~Page() override;
@@ -391,6 +395,9 @@
   // Notify |plugins_changed_observers_| that plugins have changed.
   void NotifyPluginsChanged() const;
 
+  void SetAgentGroupSchedulerForNonOrdinary(
+      std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+          agent_group_scheduler);
   void SetPageScheduler(std::unique_ptr<PageScheduler>);
 
   void InvalidateColorScheme();
@@ -484,6 +491,12 @@
   // pages or not.
   FrameScheduler::SchedulingAffectingFeatureHandle has_related_pages_;
 
+  // A non-ordinary Page has its own AgentGroupScheduler. This field
+  // needs to be declared before |page_scheduler_| to make sure it
+  // outlives it.
+  std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+      agent_group_scheduler_for_non_ordinary_;
+
   std::unique_ptr<PageScheduler> page_scheduler_;
 
   // Overrides for various media features, set from DevTools.
diff --git a/third_party/blink/renderer/core/paint/box_painter_base.cc b/third_party/blink/renderer/core/paint/box_painter_base.cc
index 91988b22..3e20c77 100644
--- a/third_party/blink/renderer/core/paint/box_painter_base.cc
+++ b/third_party/blink/renderer/core/paint/box_painter_base.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/paint/box_painter_base.h"
 
 #include "base/optional.h"
+#include "third_party/blink/renderer/core/css/native_paint_image_generator.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
@@ -318,6 +319,9 @@
   should_paint_color =
       is_bottom_layer && color.Alpha() &&
       (!should_paint_image || !layer.ImageOccludesNextLayers(doc, style));
+  should_paint_color_with_paint_worklet_image =
+      should_paint_color &&
+      RuntimeEnabledFeatures::CompositeBGColorAnimationEnabled();
 }
 
 namespace {
@@ -478,6 +482,21 @@
                          respect_orientation);
 }
 
+void FillRectWithPaintWorklet(const BoxPainterBase::FillLayerInfo& info,
+                              Node* node,
+                              const FloatRoundedRect& dest_rect,
+                              GraphicsContext& context) {
+  FloatRect src_rect = dest_rect.Rect();
+  std::unique_ptr<NativePaintImageGenerator> generator =
+      NativePaintImageGenerator::Create();
+  scoped_refptr<Image> paint_worklet_image =
+      generator->Paint(src_rect.Size(), SkColor(info.color));
+  context.DrawImageRRect(
+      paint_worklet_image.get(), Image::kSyncDecode, dest_rect, src_rect,
+      node && node->ComputedStyleRef().HasFilterInducingProperty(),
+      SkBlendMode::kSrcOver, info.respect_image_orientation);
+}
+
 inline bool PaintFastBottomLayer(Node* node,
                                  const PaintInfo& paint_info,
                                  const BoxPainterBase::FillLayerInfo& info,
@@ -563,8 +582,13 @@
   }
 
   // Paint the color if needed.
-  if (info.should_paint_color)
-    context.FillRoundedRect(color_border, info.color);
+  if (info.should_paint_color) {
+    if (info.should_paint_color_with_paint_worklet_image) {
+      FillRectWithPaintWorklet(info, node, color_border, context);
+    } else {
+      context.FillRoundedRect(color_border, info.color);
+    }
+  }
 
   // Paint the image if needed.
   if (!info.should_paint_image || !image || image_tile.IsEmpty())
@@ -737,7 +761,12 @@
   // painting area.
   if (info.is_bottom_layer && info.color.Alpha() && info.should_paint_color) {
     IntRect background_rect(PixelSnappedIntRect(scrolled_paint_rect));
-    context.FillRect(background_rect, info.color);
+    if (info.should_paint_color_with_paint_worklet_image) {
+      FillRectWithPaintWorklet(info, node, FloatRoundedRect(background_rect),
+                               context);
+    } else {
+      context.FillRect(background_rect, info.color);
+    }
   }
 
   // No progressive loading of the background image.
diff --git a/third_party/blink/renderer/core/paint/box_painter_base.h b/third_party/blink/renderer/core/paint/box_painter_base.h
index 0f87c22..cfdb240 100644
--- a/third_party/blink/renderer/core/paint/box_painter_base.h
+++ b/third_party/blink/renderer/core/paint/box_painter_base.h
@@ -134,6 +134,9 @@
     bool is_rounded_fill;
     bool should_paint_image;
     bool should_paint_color;
+    // True if we paint background color off main thread, design doc here:
+    // https://docs.google.com/document/d/1usCnwWs8HsH5FU_185q6MsrZehFmpl5QgbbB4pvHIjI/edit
+    bool should_paint_color_with_paint_worklet_image;
   };
 
  protected:
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
index f2d224d..955bd66 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
@@ -413,9 +413,7 @@
 int DedicatedWorkerGlobalScope::requestAnimationFrame(
     V8FrameRequestCallback* callback,
     ExceptionState& exception_state) {
-  auto* frame_callback =
-      MakeGarbageCollected<FrameRequestCallbackCollection::V8FrameCallback>(
-          callback);
+  auto* frame_callback = MakeGarbageCollected<V8FrameCallback>(callback);
   frame_callback->SetUseLegacyTimeBase(false);
 
   int ret = animation_frame_provider_->RegisterCallback(frame_callback);
diff --git a/third_party/blink/renderer/modules/csspaint/BUILD.gn b/third_party/blink/renderer/modules/csspaint/BUILD.gn
index e7fa2d1..3a72840f 100644
--- a/third_party/blink/renderer/modules/csspaint/BUILD.gn
+++ b/third_party/blink/renderer/modules/csspaint/BUILD.gn
@@ -14,6 +14,10 @@
     "css_paint_worklet.h",
     "document_paint_definition.cc",
     "document_paint_definition.h",
+    "native_paint_image_generator_impl.cc",
+    "native_paint_image_generator_impl.h",
+    "native_paint_worklet.cc",
+    "native_paint_worklet.h",
     "paint_rendering_context_2d.cc",
     "paint_rendering_context_2d.h",
     "paint_size.h",
diff --git a/third_party/blink/renderer/modules/csspaint/native_paint_image_generator_impl.cc b/third_party/blink/renderer/modules/csspaint/native_paint_image_generator_impl.cc
new file mode 100644
index 0000000..a62dd4a4
--- /dev/null
+++ b/third_party/blink/renderer/modules/csspaint/native_paint_image_generator_impl.cc
@@ -0,0 +1,37 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/csspaint/native_paint_image_generator_impl.h"
+
+#include "third_party/blink/renderer/modules/csspaint/native_paint_worklet.h"
+#include "third_party/blink/renderer/platform/graphics/image.h"
+
+namespace blink {
+
+std::unique_ptr<NativePaintImageGenerator>
+NativePaintImageGeneratorImpl::Create() {
+  std::unique_ptr<NativePaintWorklet> native_paint_worklet =
+      std::make_unique<NativePaintWorklet>();
+
+  DCHECK(native_paint_worklet);
+  std::unique_ptr<NativePaintImageGeneratorImpl> generator =
+      std::make_unique<NativePaintImageGeneratorImpl>(
+          std::move(native_paint_worklet));
+
+  return generator;
+}
+
+NativePaintImageGeneratorImpl::NativePaintImageGeneratorImpl(
+    std::unique_ptr<NativePaintWorklet> native_paint_worklet)
+    : native_paint_worklet_(std::move(native_paint_worklet)) {}
+
+NativePaintImageGeneratorImpl::~NativePaintImageGeneratorImpl() = default;
+
+scoped_refptr<Image> NativePaintImageGeneratorImpl::Paint(
+    const FloatSize& container_size,
+    SkColor color) {
+  return native_paint_worklet_->Paint(container_size, color);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/csspaint/native_paint_image_generator_impl.h b/third_party/blink/renderer/modules/csspaint/native_paint_image_generator_impl.h
new file mode 100644
index 0000000..897f2c1
--- /dev/null
+++ b/third_party/blink/renderer/modules/csspaint/native_paint_image_generator_impl.h
@@ -0,0 +1,36 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVE_PAINT_IMAGE_GENERATOR_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVE_PAINT_IMAGE_GENERATOR_IMPL_H_
+
+#include "third_party/blink/renderer/core/css/native_paint_image_generator.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/geometry/float_size.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class Image;
+class NativePaintWorklet;
+
+class MODULES_EXPORT NativePaintImageGeneratorImpl final
+    : public NativePaintImageGenerator {
+ public:
+  static std::unique_ptr<NativePaintImageGenerator> Create();
+
+  explicit NativePaintImageGeneratorImpl(std::unique_ptr<NativePaintWorklet>);
+  ~NativePaintImageGeneratorImpl() override;
+
+  // The |container_size| is without subpixel snapping.
+  scoped_refptr<Image> Paint(const FloatSize& container_size,
+                             SkColor color) final;
+
+ private:
+  std::unique_ptr<NativePaintWorklet> native_paint_worklet_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVE_PAINT_IMAGE_GENERATOR_IMPL_H_
diff --git a/third_party/blink/renderer/modules/csspaint/native_paint_worklet.cc b/third_party/blink/renderer/modules/csspaint/native_paint_worklet.cc
new file mode 100644
index 0000000..72a359cd
--- /dev/null
+++ b/third_party/blink/renderer/modules/csspaint/native_paint_worklet.cc
@@ -0,0 +1,29 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/csspaint/native_paint_worklet.h"
+
+#include "third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h"
+#include "third_party/blink/renderer/platform/graphics/paint_generated_image.h"
+
+namespace blink {
+
+NativePaintWorklet::NativePaintWorklet() = default;
+
+NativePaintWorklet::~NativePaintWorklet() = default;
+
+scoped_refptr<Image> NativePaintWorklet::Paint(const FloatSize& container_size,
+                                               SkColor color) {
+  PaintRenderingContext2DSettings* context_settings =
+      PaintRenderingContext2DSettings::Create();
+  auto* rendering_context = MakeGarbageCollected<PaintRenderingContext2D>(
+      RoundedIntSize(container_size), context_settings, 1, 1);
+  rendering_context->GetPaintCanvas()->drawColor(color);
+  sk_sp<PaintRecord> paint_record = rendering_context->GetRecord();
+  if (!paint_record)
+    return nullptr;
+  return PaintGeneratedImage::Create(paint_record, container_size);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/csspaint/native_paint_worklet.h b/third_party/blink/renderer/modules/csspaint/native_paint_worklet.h
new file mode 100644
index 0000000..71d0696d
--- /dev/null
+++ b/third_party/blink/renderer/modules/csspaint/native_paint_worklet.h
@@ -0,0 +1,32 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVE_PAINT_WORKLET_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVE_PAINT_WORKLET_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/geometry/float_size.h"
+#include "third_party/blink/renderer/platform/graphics/image.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace blink {
+
+class MODULES_EXPORT NativePaintWorklet {
+ public:
+  explicit NativePaintWorklet();
+  virtual ~NativePaintWorklet();
+
+  // The |container_size| is without subpixel snapping.
+  scoped_refptr<Image> Paint(const FloatSize& container_size, SkColor color);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NativePaintWorklet);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVE_PAINT_WORKLET_H_
diff --git a/third_party/blink/renderer/modules/font_access/font_manager.cc b/third_party/blink/renderer/modules/font_access/font_manager.cc
index 725d3b673..1f185d5 100644
--- a/third_party/blink/renderer/modules/font_access/font_manager.cc
+++ b/third_party/blink/renderer/modules/font_access/font_manager.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/font_access/font_iterator.h"
@@ -46,6 +47,14 @@
   return ScriptValue(script_state->GetIsolate(), result);
 }
 
+ScriptPromise FontManager::showFontChooser(ScriptState* script_state,
+                                           const QueryOptions* options) {
+  return ScriptPromise::RejectWithDOMException(
+      script_state,
+      MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotSupportedError,
+                                         "Not implemented yet"));
+}
+
 void FontManager::Trace(blink::Visitor* visitor) const {
   ScriptWrappable::Trace(visitor);
 }
diff --git a/third_party/blink/renderer/modules/font_access/font_manager.h b/third_party/blink/renderer/modules/font_access/font_manager.h
index e99b919..bf0b74f 100644
--- a/third_party/blink/renderer/modules/font_access/font_manager.h
+++ b/third_party/blink/renderer/modules/font_access/font_manager.h
@@ -14,6 +14,8 @@
 
 class ScriptState;
 class ScriptValue;
+class ScriptPromise;
+class QueryOptions;
 
 class FontManager final : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
@@ -25,7 +27,9 @@
   FontManager(const FontManager&) = delete;
   FontManager operator=(const FontManager&) = delete;
 
+  // FontManager IDL interface implementation.
   ScriptValue query(ScriptState*, ExceptionState&);
+  ScriptPromise showFontChooser(ScriptState*, const QueryOptions* options);
 
   void Trace(blink::Visitor*) const override;
 };
diff --git a/third_party/blink/renderer/modules/font_access/font_manager.idl b/third_party/blink/renderer/modules/font_access/font_manager.idl
index 46ded8e..9d0a3293 100644
--- a/third_party/blink/renderer/modules/font_access/font_manager.idl
+++ b/third_party/blink/renderer/modules/font_access/font_manager.idl
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// TODO(https://crbug.com/1062766): Update spec documents with objects as implemented.
 // https://wicg.github.io/local-font-access/
 [
     Exposed=(Window,Worker),
@@ -10,4 +9,5 @@
     RuntimeEnabled=FontAccess
 ] interface FontManager {
     [CallWith=ScriptState, RaisesException, Measure] object query();
+    [CallWith=ScriptState, RuntimeEnabled=FontAccessChooser] Promise<FontIterator> showFontChooser(optional QueryOptions options = {});
 };
diff --git a/third_party/blink/renderer/modules/font_access/idls.gni b/third_party/blink/renderer/modules/font_access/idls.gni
index ab6264c6f..b9a24af 100644
--- a/third_party/blink/renderer/modules/font_access/idls.gni
+++ b/third_party/blink/renderer/modules/font_access/idls.gni
@@ -9,6 +9,9 @@
   "font_manager.idl",
 ]
 
-modules_dictionary_idl_files = [ "font_iterator_entry.idl" ]
+modules_dictionary_idl_files = [
+  "font_iterator_entry.idl",
+  "query_options.idl",
+]
 
 modules_dependency_idl_files = [ "navigator_fonts.idl" ]
diff --git a/third_party/blink/renderer/modules/font_access/query_options.idl b/third_party/blink/renderer/modules/font_access/query_options.idl
new file mode 100644
index 0000000..e8cf81df
--- /dev/null
+++ b/third_party/blink/renderer/modules/font_access/query_options.idl
@@ -0,0 +1,9 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://wicg.github.io/local-font-access/
+dictionary QueryOptions {
+    boolean all = false;
+    sequence<ByteString> fonts;
+};
diff --git a/third_party/blink/renderer/modules/modules_initializer.cc b/third_party/blink/renderer/modules/modules_initializer.cc
index e1cfdcb..bf77517 100644
--- a/third_party/blink/renderer/modules/modules_initializer.cc
+++ b/third_party/blink/renderer/modules/modules_initializer.cc
@@ -17,6 +17,7 @@
 #include "third_party/blink/public/web/web_view_client.h"
 #include "third_party/blink/renderer/bindings/modules/v8/module_bindings_initializer.h"
 #include "third_party/blink/renderer/core/css/css_paint_image_generator.h"
+#include "third_party/blink/renderer/core/css/native_paint_image_generator.h"
 #include "third_party/blink/renderer/core/dom/context_features_client_impl.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/editing/suggestion/text_suggestion_backend_impl.h"
@@ -42,6 +43,7 @@
 #include "third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.h"
 #include "third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h"
 #include "third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.h"
+#include "third_party/blink/renderer/modules/csspaint/native_paint_image_generator_impl.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_motion_controller.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h"
@@ -123,6 +125,7 @@
   DraggedIsolatedFileSystem::Init(
       DraggedIsolatedFileSystemImpl::PrepareForDataObject);
   CSSPaintImageGenerator::Init(CSSPaintImageGeneratorImpl::Create);
+  NativePaintImageGenerator::Init(NativePaintImageGeneratorImpl::Create);
   WebDatabaseHost::GetInstance().Init();
   MediaSourceRegistryImpl::Init();
 
diff --git a/third_party/blink/renderer/modules/peerconnection/webrtc_audio_renderer_test.cc b/third_party/blink/renderer/modules/peerconnection/webrtc_audio_renderer_test.cc
index 9866080..3a2b5ec 100644
--- a/third_party/blink/renderer/modules/peerconnection/webrtc_audio_renderer_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/webrtc_audio_renderer_test.cc
@@ -21,6 +21,7 @@
 #include "third_party/blink/public/platform/modules/mediastream/web_media_stream_audio_renderer.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/web/web_heap.h"
 #include "third_party/blink/public/web/web_local_frame.h"
@@ -133,12 +134,16 @@
 // Tests crash on Android if these are defined. https://crbug.com/1119689
 #if !defined(OS_ANDROID)
         ,
+        agent_group_scheduler_(
+            blink::scheduler::WebThreadScheduler::MainThreadScheduler()
+                ->CreateAgentGroupScheduler()),
         web_view_(blink::WebView::Create(/*client=*/nullptr,
                                          /*is_hidden=*/false,
                                          /*is_inside_portal=*/false,
                                          /*compositing_enabled=*/false,
-                                         nullptr,
-                                         mojo::NullAssociatedReceiver())),
+                                         /*opener=*/nullptr,
+                                         mojo::NullAssociatedReceiver(),
+                                         *agent_group_scheduler_)),
         web_local_frame_(blink::WebLocalFrame::CreateMainFrame(
             web_view_,
             &web_local_frame_client_,
@@ -205,6 +210,7 @@
     renderer_ = nullptr;
     stream_descriptor_ = nullptr;
     source_.reset();
+    agent_group_scheduler_ = nullptr;
     blink::WebHeap::CollectAllGarbageForTesting();
   }
 
@@ -214,6 +220,8 @@
       base::UnguessableToken::Create();
   std::unique_ptr<MockAudioRendererSource> source_;
   Persistent<MediaStreamDescriptor> stream_descriptor_;
+  std::unique_ptr<blink::scheduler::WebAgentGroupScheduler>
+      agent_group_scheduler_;
   WebView* web_view_ = nullptr;
   WebLocalFrameClient web_local_frame_client_;
   WebLocalFrame* web_local_frame_ = nullptr;
diff --git a/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.h b/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.h
index b7c0577e..d7a24e9 100644
--- a/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.h
+++ b/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller.h
@@ -12,6 +12,7 @@
 #include "services/device/public/mojom/screen_orientation_lock_types.mojom-shared.h"
 #include "third_party/blink/public/mojom/widget/screen_orientation.mojom-blink.h"
 #include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/page/page_visibility_observer.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/modules/screen_orientation/web_lock_orientation_callback.h"
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_provider.cc b/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
index bc96b93..748fde67 100644
--- a/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
+++ b/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
@@ -29,8 +29,7 @@
 
 namespace {
 
-class XRFrameProviderRequestCallback
-    : public FrameRequestCallbackCollection::FrameCallback {
+class XRFrameProviderRequestCallback : public FrameCallback {
  public:
   explicit XRFrameProviderRequestCallback(XRFrameProvider* frame_provider)
       : frame_provider_(frame_provider) {}
@@ -41,8 +40,7 @@
 
   void Trace(Visitor* visitor) const override {
     visitor->Trace(frame_provider_);
-
-    FrameRequestCallbackCollection::FrameCallback::Trace(visitor);
+    FrameCallback::Trace(visitor);
   }
 
   Member<XRFrameProvider> frame_provider_;
diff --git a/third_party/blink/renderer/platform/bindings/v8_set_return_value.cc b/third_party/blink/renderer/platform/bindings/v8_set_return_value.cc
index 870dbb52..2eb318e 100644
--- a/third_party/blink/renderer/platform/bindings/v8_set_return_value.cc
+++ b/third_party/blink/renderer/platform/bindings/v8_set_return_value.cc
@@ -43,7 +43,7 @@
   return object;
 }
 
-v8::Local<v8::Value> GetInterfaceObjectExposedOnGlobal(
+v8::Local<v8::Value> GetExposedInterfaceObject(
     v8::Isolate* isolate,
     v8::Local<v8::Object> creation_context,
     const WrapperTypeInfo* wrapper_type_info) {
@@ -53,9 +53,37 @@
       ScriptState::From(creation_context->CreationContext());
   if (!script_state->ContextIsValid())
     return v8::Undefined(isolate);
+
   return script_state->PerContextData()->ConstructorForType(wrapper_type_info);
 }
 
+v8::Local<v8::Value> GetExposedNamespaceObject(
+    v8::Isolate* isolate,
+    v8::Local<v8::Object> creation_context,
+    const WrapperTypeInfo* wrapper_type_info) {
+  RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(
+      isolate, "Blink_GetInterfaceObjectExposedOnGlobal");
+  ScriptState* script_state =
+      ScriptState::From(creation_context->CreationContext());
+  if (!script_state->ContextIsValid())
+    return v8::Undefined(isolate);
+
+  v8::Context::Scope v8_context_scope(script_state->GetContext());
+  v8::Local<v8::ObjectTemplate> namespace_template =
+      wrapper_type_info->GetV8ClassTemplate(isolate, script_state->World())
+          .As<v8::ObjectTemplate>();
+  v8::Local<v8::Object> namespace_object =
+      namespace_template->NewInstance(script_state->GetContext())
+          .ToLocalChecked();
+  wrapper_type_info->InstallConditionalFeatures(
+      script_state->GetContext(), script_state->World(),
+      v8::Local<v8::Object>(),  // instance_object
+      v8::Local<v8::Object>(),  // prototype_object
+      namespace_object,         // interface_object
+      namespace_template);
+  return namespace_object;
+}
+
 }  // namespace bindings
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/bindings/v8_set_return_value.h b/third_party/blink/renderer/platform/bindings/v8_set_return_value.h
index 5e183cd..cc15c0ea 100644
--- a/third_party/blink/renderer/platform/bindings/v8_set_return_value.h
+++ b/third_party/blink/renderer/platform/bindings/v8_set_return_value.h
@@ -44,8 +44,9 @@
   // Main world or not
   enum MainWorld { kMainWorld };
 
-  // Returns the interface object of the given type.
+  // Returns the exposed object of the given type.
   enum InterfaceObject { kInterfaceObject };
+  enum NamespaceObject { kNamespaceObject };
 
   // Selects the appropriate creation context.
   static v8::Local<v8::Object> CreationContext(
@@ -363,8 +364,13 @@
       wrappable->Wrap(info.GetIsolate(), creation_context->Global()));
 }
 
-// Interface object
-PLATFORM_EXPORT v8::Local<v8::Value> GetInterfaceObjectExposedOnGlobal(
+// Exposed objects
+PLATFORM_EXPORT v8::Local<v8::Value> GetExposedInterfaceObject(
+    v8::Isolate* isolate,
+    v8::Local<v8::Object> creation_context,
+    const WrapperTypeInfo* wrapper_type_info);
+
+PLATFORM_EXPORT v8::Local<v8::Value> GetExposedNamespaceObject(
     v8::Isolate* isolate,
     v8::Local<v8::Object> creation_context,
     const WrapperTypeInfo* wrapper_type_info);
@@ -372,7 +378,14 @@
 inline void V8SetReturnValue(const v8::PropertyCallbackInfo<v8::Value>& info,
                              const WrapperTypeInfo* wrapper_type_info,
                              V8ReturnValue::InterfaceObject) {
-  info.GetReturnValue().Set(GetInterfaceObjectExposedOnGlobal(
+  info.GetReturnValue().Set(GetExposedInterfaceObject(
+      info.GetIsolate(), info.Holder(), wrapper_type_info));
+}
+
+inline void V8SetReturnValue(const v8::PropertyCallbackInfo<v8::Value>& info,
+                             const WrapperTypeInfo* wrapper_type_info,
+                             V8ReturnValue::NamespaceObject) {
+  info.GetReturnValue().Set(GetExposedNamespaceObject(
       info.GetIsolate(), info.Holder(), wrapper_type_info));
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
index 4bd8cbf..d512016 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
@@ -4,13 +4,8 @@
 
 #include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
 
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/geometry/int_rect.h"
 #include "third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h"
-#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 
 namespace blink {
 
@@ -25,25 +20,10 @@
   return total_size;
 }
 
-void PaintArtifact::Replay(GraphicsContext& graphics_context,
-                           const PropertyTreeState& replay_state,
-                           const IntPoint& offset) const {
-  Replay(*graphics_context.Canvas(), replay_state, offset);
-}
-
-void PaintArtifact::Replay(cc::PaintCanvas& canvas,
-                           const PropertyTreeState& replay_state,
-                           const IntPoint& offset) const {
-  TRACE_EVENT0("blink,benchmark", "PaintArtifact::replay");
-  canvas.drawPicture(GetPaintRecord(replay_state, offset));
-}
-
 sk_sp<PaintRecord> PaintArtifact::GetPaintRecord(
-    const PropertyTreeState& replay_state,
-    const IntPoint& offset) const {
+    const PropertyTreeState& replay_state) const {
   return PaintChunksToCcLayer::Convert(
-             PaintChunkSubset(this), replay_state,
-             gfx::Vector2dF(offset.X(), offset.Y()),
+             PaintChunkSubset(this), replay_state, gfx::Vector2dF(),
              cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
       ->ReleaseAsRecord();
 }
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
index 2aafcbdf..50e86f0 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
@@ -10,16 +10,9 @@
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
-#include "third_party/skia/include/core/SkColor.h"
-
-namespace cc {
-class PaintCanvas;
-}
 
 namespace blink {
 
-class GraphicsContext;
-
 // A PaintArtifact represents the output of painting, consisting of paint chunks
 // and display items (in DisplayItemList).
 //
@@ -63,20 +56,8 @@
   // shared with the embedder after copying to cc::DisplayItemList.
   size_t ApproximateUnsharedMemoryUsage() const;
 
-  // Draws the paint artifact to a GraphicsContext, into the ancestor state
-  // given by |replay_state|.
-  void Replay(GraphicsContext&,
-              const PropertyTreeState& replay_state,
-              const IntPoint& offset = IntPoint()) const;
-
-  // Draws the paint artifact to a PaintCanvas, into the ancestor state given
-  // by |replay_state|.
-  void Replay(cc::PaintCanvas&,
-              const PropertyTreeState& replay_state,
-              const IntPoint& offset = IntPoint()) const;
-
-  sk_sp<PaintRecord> GetPaintRecord(const PropertyTreeState& replay_state,
-                                    const IntPoint& offset = IntPoint()) const;
+  sk_sp<PaintRecord> GetPaintRecord(
+      const PropertyTreeState& replay_state) const;
 
  private:
   DisplayItemList display_item_list_;
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc b/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc
index d940b74..d3e4b97 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc
@@ -48,9 +48,7 @@
 
 void PaintRecordBuilder::EndRecording(cc::PaintCanvas& canvas,
                                       const PropertyTreeState& replay_state) {
-  paint_controller_->CommitNewDisplayItems();
-  paint_controller_->FinishCycle();
-  paint_controller_->GetPaintArtifact().Replay(canvas, replay_state);
+  canvas.drawPicture(EndRecording(replay_state));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h b/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h
index ce6f8242..446f8d459 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h
@@ -7,8 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
-#include "third_party/blink/renderer/platform/geometry/float_rect.h"
 #include "third_party/blink/renderer/platform/graphics/paint/display_item_client.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
 #include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
@@ -20,6 +18,7 @@
 }
 
 namespace blink {
+
 class GraphicsContext;
 class PaintController;
 
@@ -63,8 +62,6 @@
   PaintController* paint_controller_;
   std::unique_ptr<PaintController> own_paint_controller_;
   std::unique_ptr<GraphicsContext> context_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaintRecordBuilder);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 29fea16..9f62bbe 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -868,6 +868,12 @@
       // be enabled to make the whole feature work.
     },
     {
+      name: "FontAccessChooser",
+      // TODO(crbug.com/1000486): Add when the Origin Trial dependency bug is fixed.
+      // depends_on: ["FontAccess"],
+      status: "experimental",
+    },
+    {
       name: "FontSrcLocalMatching",
       // No status, as the web platform runtime enabled feature is controlled by
       // a Chromium level feature.
diff --git a/third_party/blink/renderer/platform/scheduler/BUILD.gn b/third_party/blink/renderer/platform/scheduler/BUILD.gn
index a74887a..7fbc5f3 100644
--- a/third_party/blink/renderer/platform/scheduler/BUILD.gn
+++ b/third_party/blink/renderer/platform/scheduler/BUILD.gn
@@ -119,6 +119,7 @@
     "main_thread/web_scoped_virtual_time_pauser.cc",
     "main_thread/widget_scheduler.cc",
     "main_thread/widget_scheduler.h",
+    "public/agent_group_scheduler.h",
     "public/aggregated_metric_reporter.h",
     "public/cooperative_scheduling_manager.h",
     "public/dummy_schedulers.h",
diff --git a/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc b/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
index f4efda3..dc727836 100644
--- a/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
@@ -4,8 +4,8 @@
 
 #include "third_party/blink/renderer/platform/scheduler/public/dummy_schedulers.h"
 
-#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/public/agent_group_scheduler.h"
 #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
 #include "third_party/blink/renderer/platform/scheduler/public/page_scheduler.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
@@ -31,6 +31,7 @@
   }
 
   PageScheduler* GetPageScheduler() const override { return page_scheduler_; }
+  AgentGroupScheduler* GetAgentGroupScheduler() override { return nullptr; }
 
   void SetPreemptedForCooperativeScheduling(Preempted) override {}
   void SetFrameVisible(bool) override {}
@@ -136,10 +137,15 @@
   DISALLOW_COPY_AND_ASSIGN(DummyPageScheduler);
 };
 
-class DummyAgentGroupScheduler : public WebAgentGroupScheduler {
+class DummyAgentGroupScheduler : public AgentGroupScheduler {
  public:
   DummyAgentGroupScheduler() = default;
   ~DummyAgentGroupScheduler() override = default;
+  AgentGroupScheduler& AsAgentGroupScheduler() override { return *this; }
+  std::unique_ptr<PageScheduler> CreatePageScheduler(
+      PageScheduler::Delegate*) override {
+    return CreateDummyPageScheduler();
+  }
   scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override {
     return base::ThreadTaskRunnerHandle::Get();
   }
@@ -196,10 +202,6 @@
     return std::make_unique<DummyAgentGroupScheduler>();
   }
 
-  std::unique_ptr<PageScheduler> CreatePageScheduler(
-      PageScheduler::Delegate*) override {
-    return std::make_unique<DummyPageScheduler>();
-  }
   WebAgentGroupScheduler* GetCurrentAgentGroupScheduler() override {
     return nullptr;
   }
@@ -268,11 +270,6 @@
     return std::make_unique<DummyAgentGroupScheduler>();
   }
 
-  std::unique_ptr<PageScheduler> CreatePageScheduler(
-      PageScheduler::Delegate*) override {
-    return std::make_unique<DummyPageScheduler>();
-  }
-
   WebAgentGroupScheduler* GetCurrentAgentGroupScheduler() override {
     return nullptr;
   }
@@ -288,6 +285,10 @@
   return std::make_unique<DummyPageScheduler>();
 }
 
+std::unique_ptr<AgentGroupScheduler> CreateDummyAgentGroupScheduler() {
+  return std::make_unique<DummyAgentGroupScheduler>();
+}
+
 std::unique_ptr<ThreadScheduler> CreateDummyThreadScheduler() {
   return std::make_unique<DummyThreadScheduler>();
 }
diff --git a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc
index de74dbd..2ec569b3 100644
--- a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc
@@ -67,11 +67,6 @@
   return nullptr;
 }
 
-std::unique_ptr<PageScheduler> SimpleThreadScheduler::CreatePageScheduler(
-    PageScheduler::Delegate* delegate) {
-  return nullptr;
-}
-
 WebAgentGroupScheduler* SimpleThreadScheduler::GetCurrentAgentGroupScheduler() {
   return nullptr;
 }
diff --git a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
index 1aa5a2a..6b80626 100644
--- a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
@@ -62,10 +62,6 @@
   // Unsupported. Return nullptr.
   std::unique_ptr<WebAgentGroupScheduler> CreateAgentGroupScheduler() override;
 
-  // Unsupported. Return nullptr, and it may cause a crash.
-  std::unique_ptr<PageScheduler> CreatePageScheduler(
-      PageScheduler::Delegate*) override;
-
   // Return nullptr
   WebAgentGroupScheduler* GetCurrentAgentGroupScheduler() override;
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/agent_group_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/agent_group_scheduler_impl.cc
index 293369bc..0aacf6d 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/agent_group_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/agent_group_scheduler_impl.cc
@@ -6,10 +6,17 @@
 
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/public/dummy_schedulers.h"
 
 namespace blink {
 namespace scheduler {
 
+// static
+std::unique_ptr<WebAgentGroupScheduler>
+WebAgentGroupScheduler::CreateForTesting() {
+  return CreateDummyAgentGroupScheduler();
+}
+
 MainThreadTaskQueue::QueueCreationParams DefaultTaskQueueCreationParams(
     AgentGroupSchedulerImpl* agent_group_scheduler_impl) {
   return MainThreadTaskQueue::QueueCreationParams(
@@ -24,12 +31,26 @@
           DefaultTaskQueueCreationParams(this))),
       default_task_runner_(default_task_queue_->CreateTaskRunner(
           TaskType::kMainThreadTaskQueueDefault)),
-      main_thread_scheduler_(main_thread_scheduler) {}
+      main_thread_scheduler_(main_thread_scheduler) {
+  DCHECK(!default_task_queue_->GetFrameScheduler());
+  DCHECK_EQ(default_task_queue_->GetAgentGroupScheduler(), this);
+}
 
 AgentGroupSchedulerImpl::~AgentGroupSchedulerImpl() {
   default_task_queue_->ShutdownTaskQueue();
   main_thread_scheduler_.RemoveAgentGroupScheduler(this);
 }
 
+std::unique_ptr<PageScheduler> AgentGroupSchedulerImpl::CreatePageScheduler(
+    PageScheduler::Delegate* delegate) {
+  auto page_scheduler = std::make_unique<PageSchedulerImpl>(delegate, *this);
+  main_thread_scheduler_.AddPageScheduler(page_scheduler.get());
+  return page_scheduler;
+}
+
+AgentGroupScheduler& AgentGroupSchedulerImpl::AsAgentGroupScheduler() {
+  return *this;
+}
+
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/agent_group_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/agent_group_scheduler_impl.h
index 703e7a9..01dbd85 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/agent_group_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/agent_group_scheduler_impl.h
@@ -6,8 +6,8 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_AGENT_GROUP_SCHEDULER_IMPL_H_
 
 #include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/public/agent_group_scheduler.h"
 
 namespace base {
 class SingleThreadTaskRunner;
@@ -20,7 +20,7 @@
 
 // AgentGroupScheduler implementation which schedules per-AgentSchedulingGroup
 // tasks.
-class PLATFORM_EXPORT AgentGroupSchedulerImpl : public WebAgentGroupScheduler {
+class PLATFORM_EXPORT AgentGroupSchedulerImpl : public AgentGroupScheduler {
  public:
   explicit AgentGroupSchedulerImpl(
       MainThreadSchedulerImpl& main_thread_scheduler);
@@ -28,12 +28,15 @@
   AgentGroupSchedulerImpl& operator=(const AgentGroupSchedulerImpl&) = delete;
   ~AgentGroupSchedulerImpl() override;
 
+  std::unique_ptr<PageScheduler> CreatePageScheduler(
+      PageScheduler::Delegate*) override;
   scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override {
     return default_task_runner_;
   }
   MainThreadSchedulerImpl& GetMainThreadScheduler() {
     return main_thread_scheduler_;
   }
+  AgentGroupScheduler& AsAgentGroupScheduler() override;
 
  private:
   scoped_refptr<MainThreadTaskQueue> default_task_queue_;
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
index 36e46eb..20617597 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -584,7 +584,7 @@
   return main_thread_scheduler_->ControlTaskRunner();
 }
 
-AgentGroupSchedulerImpl* FrameSchedulerImpl::GetAgentGroupScheduler() {
+WebAgentGroupScheduler* FrameSchedulerImpl::GetAgentGroupScheduler() {
   return parent_page_scheduler_
              ? &parent_page_scheduler_->GetAgentGroupScheduler()
              : nullptr;
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
index 4fc0c0c0..278956f3 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
@@ -110,7 +110,7 @@
   std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
   CreateResourceLoadingTaskRunnerHandle() override;
 
-  AgentGroupSchedulerImpl* GetAgentGroupScheduler();
+  WebAgentGroupScheduler* GetAgentGroupScheduler() override;
   PageScheduler* GetPageScheduler() const override;
   void DidStartProvisionalLoad(bool is_main_frame) override;
   void DidCommitProvisionalLoad(bool is_web_history_inert_commit,
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
index a78a6ee0..eedb64bb 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
@@ -26,6 +26,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/switches.h"
+#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
 #include "third_party/blink/renderer/platform/scheduler/common/features.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
@@ -60,9 +61,11 @@
 // returns the PageScheduler as a PageSchedulerImpl.
 std::unique_ptr<PageSchedulerImpl> CreatePageScheduler(
     PageScheduler::Delegate* page_scheduler_delegate,
-    MainThreadSchedulerImpl* scheduler) {
+    MainThreadSchedulerImpl* scheduler,
+    WebAgentGroupScheduler& agent_group_scheduler) {
   std::unique_ptr<PageScheduler> page_scheduler =
-      scheduler->CreatePageScheduler(page_scheduler_delegate);
+      agent_group_scheduler.AsAgentGroupScheduler().CreatePageScheduler(
+          page_scheduler_delegate);
   std::unique_ptr<PageSchedulerImpl> page_scheduler_impl(
       static_cast<PageSchedulerImpl*>(page_scheduler.release()));
   return page_scheduler_impl;
@@ -205,7 +208,9 @@
             nullptr, task_environment_.GetMainThreadTaskRunner(),
             task_environment_.GetMockTickClock()),
         base::nullopt);
-    page_scheduler_ = CreatePageScheduler(nullptr, scheduler_.get());
+    agent_group_scheduler_ = scheduler_->CreateAgentGroupScheduler();
+    page_scheduler_ =
+        CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
     frame_scheduler_delegate_ = std::make_unique<
         testing::StrictMock<FrameSchedulerDelegateForTesting>>();
     frame_scheduler_ = CreateFrameScheduler(
@@ -233,6 +238,7 @@
     throttleable_task_queue_.reset();
     frame_scheduler_.reset();
     page_scheduler_.reset();
+    agent_group_scheduler_.reset();
     scheduler_->Shutdown();
     scheduler_.reset();
     frame_scheduler_delegate_.reset();
@@ -409,6 +415,7 @@
   base::test::ScopedFeatureList feature_list_;
   base::test::TaskEnvironment task_environment_;
   std::unique_ptr<MainThreadSchedulerImpl> scheduler_;
+  std::unique_ptr<WebAgentGroupScheduler> agent_group_scheduler_;
   std::unique_ptr<PageSchedulerImpl> page_scheduler_;
   std::unique_ptr<FrameSchedulerImpl> frame_scheduler_;
   std::unique_ptr<testing::StrictMock<FrameSchedulerDelegateForTesting>>
@@ -2874,8 +2881,10 @@
 
 TEST_F(FrameSchedulerImplTest, ReportFMPAndFCPForMainFrames) {
   MockMainThreadScheduler mock_main_thread_scheduler{task_environment_};
-  std::unique_ptr<PageSchedulerImpl> page_scheduler =
-      CreatePageScheduler(nullptr, &mock_main_thread_scheduler);
+  std::unique_ptr<WebAgentGroupScheduler> agent_group_scheduler =
+      mock_main_thread_scheduler.CreateAgentGroupScheduler();
+  std::unique_ptr<PageSchedulerImpl> page_scheduler = CreatePageScheduler(
+      nullptr, &mock_main_thread_scheduler, *agent_group_scheduler);
 
   std::unique_ptr<FrameSchedulerImpl> main_frame_scheduler =
       CreateFrameScheduler(page_scheduler.get(), nullptr, nullptr,
@@ -2888,13 +2897,16 @@
 
   main_frame_scheduler = nullptr;
   page_scheduler = nullptr;
+  agent_group_scheduler = nullptr;
   mock_main_thread_scheduler.Shutdown();
 }
 
 TEST_F(FrameSchedulerImplTest, DontReportFMPAndFCPForSubframes) {
   MockMainThreadScheduler mock_main_thread_scheduler{task_environment_};
-  std::unique_ptr<PageSchedulerImpl> page_scheduler =
-      CreatePageScheduler(nullptr, &mock_main_thread_scheduler);
+  std::unique_ptr<WebAgentGroupScheduler> agent_group_scheduler =
+      mock_main_thread_scheduler.CreateAgentGroupScheduler();
+  std::unique_ptr<PageSchedulerImpl> page_scheduler = CreatePageScheduler(
+      nullptr, &mock_main_thread_scheduler, *agent_group_scheduler);
 
   std::unique_ptr<FrameSchedulerImpl> subframe_scheduler =
       CreateFrameScheduler(page_scheduler.get(), nullptr, nullptr,
@@ -2907,6 +2919,7 @@
 
   subframe_scheduler = nullptr;
   page_scheduler = nullptr;
+  agent_group_scheduler = nullptr;
   mock_main_thread_scheduler.Shutdown();
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
index a09d42f..10b2da3 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
@@ -48,7 +48,10 @@
             nullptr, task_environment_.GetMainThreadTaskRunner(),
             task_environment_.GetMockTickClock()),
         base::nullopt);
-    page_scheduler_ = scheduler_->CreatePageScheduler(nullptr);
+    agent_group_scheduler_ = scheduler_->CreateAgentGroupScheduler();
+    page_scheduler_ =
+        agent_group_scheduler_->AsAgentGroupScheduler().CreatePageScheduler(
+            nullptr);
     frame_scheduler_ = page_scheduler_->CreateFrameScheduler(
         nullptr, nullptr, FrameScheduler::FrameType::kSubframe);
     frame_task_queue_controller_ = std::make_unique<FrameTaskQueueController>(
@@ -60,6 +63,7 @@
     frame_task_queue_controller_.reset();
     frame_scheduler_.reset();
     page_scheduler_.reset();
+    agent_group_scheduler_.reset();
     scheduler_->Shutdown();
     scheduler_.reset();
   }
@@ -113,6 +117,7 @@
  protected:
   base::test::TaskEnvironment task_environment_;
   std::unique_ptr<MainThreadSchedulerImpl> scheduler_;
+  std::unique_ptr<WebAgentGroupScheduler> agent_group_scheduler_;
   std::unique_ptr<PageScheduler> page_scheduler_;
   std::unique_ptr<FrameScheduler> frame_scheduler_;
   std::unique_ptr<FrameTaskQueueController> frame_task_queue_controller_;
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
index 110efe42..34b36e20 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -2348,32 +2348,12 @@
   return agent_group_scheduler;
 }
 
-AgentGroupSchedulerImpl& MainThreadSchedulerImpl::EnsureAgentGroupScheduler() {
-  // TODO(crbug/1113102): Currently, MainThreadSchedulerImpl owns
-  // AgentGroupSchedulerImpl
-  if (!agent_group_scheduler_) {
-    agent_group_scheduler_ = std::make_unique<AgentGroupSchedulerImpl>(*this);
-    AddAgentGroupScheduler(agent_group_scheduler_.get());
-  }
-  return *agent_group_scheduler_.get();
-}
-
 void MainThreadSchedulerImpl::RemoveAgentGroupScheduler(
     AgentGroupSchedulerImpl* agent_group_scheduler) {
   DCHECK(agent_group_schedulers_.Contains(agent_group_scheduler));
   agent_group_schedulers_.erase(agent_group_scheduler);
 }
 
-std::unique_ptr<PageScheduler> MainThreadSchedulerImpl::CreatePageScheduler(
-    PageScheduler::Delegate* delegate) {
-  // TODO(crbug/1113102): we'll use the singleton AgentGroupScheduler instance
-  // tentatively.
-  auto page_scheduler = std::make_unique<PageSchedulerImpl>(
-      delegate, EnsureAgentGroupScheduler() /* tentative */);
-  AddPageScheduler(page_scheduler.get());
-  return page_scheduler;
-}
-
 WebAgentGroupScheduler*
 MainThreadSchedulerImpl::GetCurrentAgentGroupScheduler() {
   helper_.CheckOnValidThread();
@@ -2381,7 +2361,7 @@
 }
 
 void MainThreadSchedulerImpl::SetCurrentAgentGroupScheduler(
-    AgentGroupSchedulerImpl* agent_group_scheduler_impl) {
+    WebAgentGroupScheduler* agent_group_scheduler) {
   helper_.CheckOnValidThread();
   if (current_agent_group_scheduler_) {
     TRACE_EVENT_NESTABLE_ASYNC_END1(
@@ -2393,7 +2373,7 @@
         TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
         "scheduler.thread_scope", this);
   }
-  current_agent_group_scheduler_ = agent_group_scheduler_impl;
+  current_agent_group_scheduler_ = agent_group_scheduler;
   if (current_agent_group_scheduler_) {
     TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
         TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
@@ -2437,9 +2417,9 @@
 }
 
 void MainThreadSchedulerImpl::AddAgentGroupScheduler(
-    AgentGroupSchedulerImpl* agent_group_scheduler_impl) {
+    AgentGroupSchedulerImpl* agent_group_scheduler) {
   bool is_new_entry =
-      agent_group_schedulers_.insert(agent_group_scheduler_impl).is_new_entry;
+      agent_group_schedulers_.insert(agent_group_scheduler).is_new_entry;
   DCHECK(is_new_entry);
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
index c4e87ef1..38627685 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -220,14 +220,9 @@
   scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override;
   scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override;
   std::unique_ptr<WebAgentGroupScheduler> CreateAgentGroupScheduler() override;
-  // TODO(crbug/1113102): rename to CreateAgentGroupScheduler when integrate
-  // with AgentSchedulingGroup
-  AgentGroupSchedulerImpl& EnsureAgentGroupScheduler();
-  std::unique_ptr<PageScheduler> CreatePageScheduler(
-      PageScheduler::Delegate*) override;
   WebAgentGroupScheduler* GetCurrentAgentGroupScheduler() override;
   void SetCurrentAgentGroupScheduler(
-      AgentGroupSchedulerImpl* agent_group_scheduler_impl);
+      WebAgentGroupScheduler* agent_group_scheduler);
   std::unique_ptr<ThreadScheduler::RendererPauseHandle> PauseScheduler()
       override;
   base::TimeTicks MonotonicallyIncreasingVirtualTime() override;
@@ -311,6 +306,7 @@
   void MaybeAdvanceVirtualTime(base::TimeTicks new_virtual_time);
 
   void RemoveAgentGroupScheduler(AgentGroupSchedulerImpl*);
+  void AddPageScheduler(PageSchedulerImpl*);
   void RemovePageScheduler(PageSchedulerImpl*);
 
   void OnFrameAdded(const FrameSchedulerImpl& frame_scheduler);
@@ -475,7 +471,6 @@
   static const char* TimeDomainTypeToString(TimeDomainType domain_type);
 
   void AddAgentGroupScheduler(AgentGroupSchedulerImpl*);
-  void AddPageScheduler(PageSchedulerImpl*);
 
   bool IsAnyMainFrameWaitingForFirstContentfulPaint() const;
   bool IsAnyMainFrameWaitingForFirstMeaningfulPaint() const;
@@ -1021,9 +1016,7 @@
   PollableThreadSafeFlag policy_may_need_update_;
   PollableThreadSafeFlag notify_agent_strategy_task_posted_;
   WTF::HashSet<AgentGroupSchedulerImpl*> agent_group_schedulers_;
-  AgentGroupSchedulerImpl* current_agent_group_scheduler_{nullptr};
-  // TODO(crbug/1113102): tentatively, we hold AgentGroupSchedulerImpl here.
-  std::unique_ptr<AgentGroupSchedulerImpl> agent_group_scheduler_;
+  WebAgentGroupScheduler* current_agent_group_scheduler_{nullptr};
 
   base::WeakPtrFactory<MainThreadSchedulerImpl> weak_factory_{this};
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
index f3f19ea6..7daa88b78 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
@@ -70,9 +70,11 @@
 // returns the PageScheduler as a PageSchedulerImpl.
 std::unique_ptr<PageSchedulerImpl> CreatePageScheduler(
     PageScheduler::Delegate* page_scheduler_delegate,
-    ThreadSchedulerImpl* scheduler) {
+    ThreadSchedulerImpl* scheduler,
+    WebAgentGroupScheduler& agent_group_scheduler) {
   std::unique_ptr<PageScheduler> page_scheduler =
-      scheduler->CreatePageScheduler(page_scheduler_delegate);
+      agent_group_scheduler.AsAgentGroupScheduler().CreatePageScheduler(
+          page_scheduler_delegate);
   std::unique_ptr<PageSchedulerImpl> page_scheduler_impl(
       static_cast<PageSchedulerImpl*>(page_scheduler.release()));
   return page_scheduler_impl;
@@ -302,11 +304,12 @@
 
 class MockPageSchedulerImpl : public PageSchedulerImpl {
  public:
-  explicit MockPageSchedulerImpl(AgentGroupSchedulerImpl& agent_group_scheduler)
+  explicit MockPageSchedulerImpl(MainThreadSchedulerImpl* main_thread_scheduler,
+                                 AgentGroupSchedulerImpl& agent_group_scheduler)
       : PageSchedulerImpl(nullptr, agent_group_scheduler) {
     // This would normally be called by
     // MainThreadSchedulerImpl::CreatePageScheduler.
-    agent_group_scheduler.GetMainThreadScheduler().AddPageScheduler(this);
+    main_thread_scheduler->AddPageScheduler(this);
 
     ON_CALL(*this, IsWaitingForMainFrameContentfulPaint)
         .WillByDefault(Return(true));
@@ -443,8 +446,10 @@
     idle_task_runner_ = scheduler_->IdleTaskRunner();
     v8_task_runner_ = scheduler_->V8TaskQueue()->task_runner();
 
+    agent_group_scheduler_ = scheduler_->CreateAgentGroupScheduler();
     page_scheduler_ = std::make_unique<NiceMock<MockPageSchedulerImpl>>(
-        scheduler_->EnsureAgentGroupScheduler());
+        scheduler_.get(),
+        static_cast<AgentGroupSchedulerImpl&>(*agent_group_scheduler_));
     main_frame_scheduler_ =
         CreateFrameScheduler(page_scheduler_.get(), nullptr, nullptr,
                              FrameScheduler::FrameType::kMainFrame);
@@ -500,6 +505,7 @@
     widget_scheduler_.reset();
     main_frame_scheduler_.reset();
     page_scheduler_.reset();
+    agent_group_scheduler_.reset();
     scheduler_->Shutdown();
     base::RunLoop().RunUntilIdle();
     scheduler_.reset();
@@ -943,6 +949,7 @@
   scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
 
   std::unique_ptr<MainThreadSchedulerImplForTest> scheduler_;
+  std::unique_ptr<WebAgentGroupScheduler> agent_group_scheduler_;
   std::unique_ptr<MockPageSchedulerImpl> page_scheduler_;
   std::unique_ptr<FrameSchedulerImpl> main_frame_scheduler_;
   std::unique_ptr<WebWidgetScheduler> widget_scheduler_;
@@ -3169,7 +3176,8 @@
 }
 
 TEST_F(MainThreadSchedulerImplTest, EnableVirtualTimeAfterThrottling) {
-  auto page_scheduler = CreatePageScheduler(nullptr, scheduler_.get());
+  auto page_scheduler =
+      CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
 
   std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
       CreateFrameScheduler(page_scheduler.get(), nullptr, nullptr,
@@ -3299,7 +3307,7 @@
   // traced value. This test checks that no internal checks fire during this.
 
   std::unique_ptr<PageSchedulerImpl> page_scheduler1 =
-      CreatePageScheduler(nullptr, scheduler_.get());
+      CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
   scheduler_->AddPageScheduler(page_scheduler1.get());
 
   std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
@@ -3307,7 +3315,7 @@
                            FrameScheduler::FrameType::kSubframe);
 
   std::unique_ptr<PageSchedulerImpl> page_scheduler2 =
-      CreatePageScheduler(nullptr, scheduler_.get());
+      CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
   scheduler_->AddPageScheduler(page_scheduler2.get());
 
   CPUTimeBudgetPool* time_budget_pool =
@@ -3393,10 +3401,12 @@
   page_scheduler_.reset();
 
   std::unique_ptr<PageScheduler> sched_1 =
-      scheduler_->CreatePageScheduler(nullptr);
+      agent_group_scheduler_->AsAgentGroupScheduler().CreatePageScheduler(
+          nullptr);
   sched_1->SetPageVisible(false);
   std::unique_ptr<PageScheduler> sched_2 =
-      scheduler_->CreatePageScheduler(nullptr);
+      agent_group_scheduler_->AsAgentGroupScheduler().CreatePageScheduler(
+          nullptr);
   sched_2->SetPageVisible(false);
 
   Vector<String> run_order;
@@ -3415,7 +3425,8 @@
 
   run_order.clear();
   std::unique_ptr<PageScheduler> sched_3 =
-      scheduler_->CreatePageScheduler(nullptr);
+      agent_group_scheduler_->AsAgentGroupScheduler().CreatePageScheduler(
+          nullptr);
   sched_3->SetPageVisible(false);
   base::RunLoop().RunUntilIdle();
   EXPECT_THAT(run_order, testing::ElementsAre("C2"));
@@ -3909,7 +3920,8 @@
 };
 
 TEST_F(DisableNonMainTimerQueuesUntilFMPTest, DisablesOnlyNonMainTimerQueue) {
-  auto page_scheduler = CreatePageScheduler(nullptr, scheduler_.get());
+  auto page_scheduler =
+      CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
 
   NiceMock<MockFrameDelegate> frame_delegate{};
   std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
@@ -3932,7 +3944,8 @@
 
 TEST_F(DisableNonMainTimerQueuesUntilFMPTest,
        ShouldNotifyAgentStrategyOnInput) {
-  auto page_scheduler = CreatePageScheduler(nullptr, scheduler_.get());
+  auto page_scheduler =
+      CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
 
   NiceMock<MockFrameDelegate> frame_delegate{};
   std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
@@ -3973,7 +3986,8 @@
 };
 
 TEST_F(BestEffortNonMainQueuesUntilOnLoadTest, DeprioritizesAllNonMainQueues) {
-  auto page_scheduler = CreatePageScheduler(nullptr, scheduler_.get());
+  auto page_scheduler =
+      CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
 
   NiceMock<MockFrameDelegate> frame_delegate{};
   std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
@@ -4006,7 +4020,8 @@
 TEST_F(BestEffortNonMainQueuesUntilOnFMPTimeoutTest,
        DeprioritizesNonMainQueues) {
   auto page_scheduler = CreatePageScheduler(
-      /* page_scheduler_delegate= */ nullptr, scheduler_.get());
+      /* page_scheduler_delegate= */ nullptr, scheduler_.get(),
+      *agent_group_scheduler_);
 
   NiceMock<MockFrameDelegate> frame_delegate{};
   std::unique_ptr<FrameSchedulerImpl> frame_scheduler = CreateFrameScheduler(
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc
index da779c29..599869e 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc
@@ -111,6 +111,7 @@
       freeze_when_keep_active_(params.freeze_when_keep_active),
       web_scheduling_priority_(params.web_scheduling_priority),
       main_thread_scheduler_(main_thread_scheduler),
+      agent_group_scheduler_(params.agent_group_scheduler),
       frame_scheduler_(params.frame_scheduler) {
   if (GetTaskQueueImpl() && spec.should_notify_observers) {
     // TaskQueueImpl may be null for tests.
@@ -187,7 +188,7 @@
   TaskQueue::ShutdownTaskQueue();
 }
 
-AgentGroupSchedulerImpl* MainThreadTaskQueue::GetAgentGroupScheduler() {
+WebAgentGroupScheduler* MainThreadTaskQueue::GetAgentGroupScheduler() {
   DCHECK(task_runner()->BelongsToCurrentThread());
   if (agent_group_scheduler_) {
     DCHECK(!frame_scheduler_);
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
index 13dfa0fac..aca96fe 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
@@ -235,6 +235,7 @@
     explicit QueueCreationParams(QueueType queue_type)
         : queue_type(queue_type),
           spec(NameForQueueType(queue_type)),
+          agent_group_scheduler(nullptr),
           frame_scheduler(nullptr),
           freeze_when_keep_active(false) {}
 
@@ -408,7 +409,7 @@
   // Override base method to notify MainThreadScheduler about shutdown queue.
   void ShutdownTaskQueue() override;
 
-  AgentGroupSchedulerImpl* GetAgentGroupScheduler();
+  WebAgentGroupScheduler* GetAgentGroupScheduler();
 
   FrameSchedulerImpl* GetFrameScheduler() const;
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
index 6f798db..e177b7cb 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
@@ -48,9 +48,11 @@
 // returns the PageScheduler as a PageSchedulerImpl.
 std::unique_ptr<PageSchedulerImpl> CreatePageScheduler(
     PageScheduler::Delegate* page_scheduler_delegate,
-    MainThreadSchedulerImpl* scheduler) {
+    MainThreadSchedulerImpl* scheduler,
+    WebAgentGroupScheduler& agent_group_scheduler) {
   std::unique_ptr<PageScheduler> page_scheduler =
-      scheduler->CreatePageScheduler(page_scheduler_delegate);
+      agent_group_scheduler.AsAgentGroupScheduler().CreatePageScheduler(
+          page_scheduler_delegate);
   std::unique_ptr<PageSchedulerImpl> page_scheduler_impl(
       static_cast<PageSchedulerImpl*>(page_scheduler.release()));
   return page_scheduler_impl;
@@ -114,9 +116,11 @@
         base::sequence_manager::SequenceManagerForTest::Create(
             nullptr, test_task_runner_, test_task_runner_->GetMockTickClock()),
         base::nullopt);
+    agent_group_scheduler_ = scheduler_->CreateAgentGroupScheduler();
     page_scheduler_delegate_ = std::make_unique<MockPageSchedulerDelegate>();
     page_scheduler_ =
-        CreatePageScheduler(page_scheduler_delegate_.get(), scheduler_.get());
+        CreatePageScheduler(page_scheduler_delegate_.get(), scheduler_.get(),
+                            *agent_group_scheduler_);
     frame_scheduler_ =
         CreateFrameScheduler(page_scheduler_.get(), nullptr, nullptr,
                              FrameScheduler::FrameType::kSubframe);
@@ -125,6 +129,7 @@
   void TearDown() override {
     frame_scheduler_.reset();
     page_scheduler_.reset();
+    agent_group_scheduler_.reset();
     scheduler_->Shutdown();
     scheduler_.reset();
   }
@@ -271,6 +276,7 @@
 
   scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
   std::unique_ptr<MainThreadSchedulerImpl> scheduler_;
+  std::unique_ptr<WebAgentGroupScheduler> agent_group_scheduler_;
   std::unique_ptr<PageSchedulerImpl> page_scheduler_;
   std::unique_ptr<FrameSchedulerImpl> frame_scheduler_;
   std::unique_ptr<MockPageSchedulerDelegate> page_scheduler_delegate_;
@@ -388,7 +394,7 @@
 
 TEST_F(PageSchedulerImplTest, RepeatingTimers_OneBackgroundOneForeground) {
   std::unique_ptr<PageSchedulerImpl> page_scheduler2 =
-      CreatePageScheduler(nullptr, scheduler_.get());
+      CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
   std::unique_ptr<FrameSchedulerImpl> frame_scheduler2 =
       CreateFrameScheduler(page_scheduler2.get(), nullptr, nullptr,
                            FrameScheduler::FrameType::kSubframe);
@@ -1125,7 +1131,8 @@
       budget_background_throttling_enabler(true);
 
   InitializeTrialParams();
-  page_scheduler_ = CreatePageScheduler(nullptr, scheduler_.get());
+  page_scheduler_ =
+      CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
   EXPECT_FALSE(page_scheduler_->IsCPUTimeThrottled());
 
   Vector<base::TimeTicks> run_times;
@@ -1189,7 +1196,7 @@
 
   InitializeTrialParams();
   std::unique_ptr<PageSchedulerImpl> page_scheduler =
-      CreatePageScheduler(nullptr, scheduler_.get());
+      CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
 
   Vector<base::TimeTicks> run_times;
 
@@ -1371,7 +1378,7 @@
   scheduler_->SetSchedulerKeepActive(true);
 
   std::unique_ptr<PageSchedulerImpl> page_scheduler2 =
-      CreatePageScheduler(nullptr, scheduler_.get());
+      CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_);
 
   EXPECT_TRUE(page_scheduler_->KeepActive());
   EXPECT_TRUE(page_scheduler2->KeepActive());
diff --git a/third_party/blink/renderer/platform/scheduler/public/agent_group_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/agent_group_scheduler.h
new file mode 100644
index 0000000..a8c17eb
--- /dev/null
+++ b/third_party/blink/renderer/platform/scheduler/public/agent_group_scheduler.h
@@ -0,0 +1,28 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_AGENT_GROUP_SCHEDULER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_AGENT_GROUP_SCHEDULER_H_
+
+#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/renderer/platform/scheduler/public/page_scheduler.h"
+
+namespace blink {
+
+// AgentGroupScheduler schedules per-AgentSchedulingGroup tasks.
+// AgentSchedulingGroup is Blink's unit of scheduling and performance isolation.
+class BLINK_PLATFORM_EXPORT AgentGroupScheduler
+    : public scheduler::WebAgentGroupScheduler {
+ public:
+  // Creates a new PageScheduler for a given Page. Must be called from the
+  // associated WebThread.
+  virtual std::unique_ptr<PageScheduler> CreatePageScheduler(
+      PageScheduler::Delegate*) = 0;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_AGENT_GROUP_SCHEDULER_H_
diff --git a/third_party/blink/renderer/platform/scheduler/public/dummy_schedulers.h b/third_party/blink/renderer/platform/scheduler/public/dummy_schedulers.h
index 83a775a..186cee66 100644
--- a/third_party/blink/renderer/platform/scheduler/public/dummy_schedulers.h
+++ b/third_party/blink/renderer/platform/scheduler/public/dummy_schedulers.h
@@ -12,6 +12,7 @@
 namespace blink {
 class FrameScheduler;
 class PageScheduler;
+class AgentGroupScheduler;
 class ThreadScheduler;
 
 namespace scheduler {
@@ -33,6 +34,8 @@
 
 PLATFORM_EXPORT std::unique_ptr<FrameScheduler> CreateDummyFrameScheduler();
 PLATFORM_EXPORT std::unique_ptr<PageScheduler> CreateDummyPageScheduler();
+PLATFORM_EXPORT std::unique_ptr<AgentGroupScheduler>
+CreateDummyAgentGroupScheduler();
 PLATFORM_EXPORT std::unique_ptr<ThreadScheduler> CreateDummyThreadScheduler();
 PLATFORM_EXPORT std::unique_ptr<WebThreadScheduler>
 CreateDummyWebThreadScheduler();
diff --git a/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h
index f458a4a..4592c47a 100644
--- a/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h
@@ -27,6 +27,10 @@
 
 namespace blink {
 
+namespace scheduler {
+class WebAgentGroupScheduler;
+}  // namespace scheduler
+
 class PageScheduler;
 class WebSchedulingTaskQueue;
 
@@ -125,6 +129,9 @@
   // Returns the parent PageScheduler.
   virtual PageScheduler* GetPageScheduler() const = 0;
 
+  // Returns the parent AgentGroupScheduler.
+  virtual scheduler::WebAgentGroupScheduler* GetAgentGroupScheduler() = 0;
+
   // Returns a WebScopedVirtualTimePauser which can be used to vote for pausing
   // virtual time. Virtual time will be paused if any WebScopedVirtualTimePauser
   // votes to pause it, and only unpaused only if all
diff --git a/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
index aaa4643b..a7e2d1e 100644
--- a/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
@@ -116,13 +116,10 @@
   virtual std::unique_ptr<scheduler::WebAgentGroupScheduler>
   CreateAgentGroupScheduler() = 0;
 
-  // Creates a new PageScheduler for a given Page. Must be called from the
-  // associated WebThread.
-  virtual std::unique_ptr<PageScheduler> CreatePageScheduler(
-      PageScheduler::Delegate*) = 0;
-
-  // Return the current active AgentGroupScheduler.
-  // If there is no active AgentGroupScheduler, it returns nullptr.
+  // The current active AgentGroupScheduler is set when the task gets
+  // started (i.e., OnTaskStarted) and unset when the task gets
+  // finished (i.e., OnTaskCompleted). GetCurrentAgentGroupScheduler()
+  // returns nullptr in task observers.
   virtual scheduler::WebAgentGroupScheduler*
   GetCurrentAgentGroupScheduler() = 0;
 
diff --git a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc
index 18c03a3b..4fd8354 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc
@@ -77,13 +77,6 @@
   return nullptr;
 }
 
-std::unique_ptr<blink::PageScheduler>
-NonMainThreadSchedulerImpl::CreatePageScheduler(
-    PageScheduler::Delegate* delegate) {
-  NOTREACHED();
-  return nullptr;
-}
-
 WebAgentGroupScheduler*
 NonMainThreadSchedulerImpl::GetCurrentAgentGroupScheduler() {
   NOTREACHED();
diff --git a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h
index d3dd6972..9822d33 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h
@@ -71,8 +71,6 @@
                            base::TimeDelta delay,
                            Thread::IdleTask task) override;
   std::unique_ptr<WebAgentGroupScheduler> CreateAgentGroupScheduler() override;
-  std::unique_ptr<PageScheduler> CreatePageScheduler(
-      PageScheduler::Delegate*) override;
   WebAgentGroupScheduler* GetCurrentAgentGroupScheduler() override;
   std::unique_ptr<RendererPauseHandle> PauseScheduler() override
       WARN_UNUSED_RESULT;
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc
index b8e0b12..2ce2416 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc
@@ -112,7 +112,11 @@
                 task_environment_.GetMainThreadTaskRunner(),
                 task_environment_.GetMockTickClock()),
             base::nullopt)),
-        page_scheduler_(main_thread_scheduler_->CreatePageScheduler(nullptr)),
+        agent_group_scheduler_(
+            main_thread_scheduler_->CreateAgentGroupScheduler()),
+        page_scheduler_(
+            agent_group_scheduler_->AsAgentGroupScheduler().CreatePageScheduler(
+                nullptr)),
         frame_scheduler_(page_scheduler_->CreateFrameScheduler(
             nullptr,
             nullptr,
@@ -121,12 +125,14 @@
   ~WorkerSchedulerProxyTest() override {
     frame_scheduler_.reset();
     page_scheduler_.reset();
+    agent_group_scheduler_.reset();
     main_thread_scheduler_->Shutdown();
   }
 
  protected:
   base::test::TaskEnvironment task_environment_;
   std::unique_ptr<MainThreadSchedulerImpl> main_thread_scheduler_;
+  std::unique_ptr<WebAgentGroupScheduler> agent_group_scheduler_;
   std::unique_ptr<PageScheduler> page_scheduler_;
   std::unique_ptr<FrameScheduler> frame_scheduler_;
 };
diff --git a/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc b/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
index 0a338ce..9abf3db1 100644
--- a/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
+++ b/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
@@ -685,8 +685,7 @@
             gpu_memory_buffer_support_->CreateGpuMemoryBufferImplFromHandle(
                 buffer_context->TakeGpuMemoryBufferHandle(),
                 gfx::Size(info->coded_size), gfx_format,
-                gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE,
-                base::DoNothing());
+                gfx::BufferUsage::SCANOUT_VEA_CPU_READ, base::DoNothing());
         buffer_context->SetGpuMemoryBuffer(std::move(gmb));
       }
       CHECK(buffer_context->GetGpuMemoryBuffer());
@@ -697,8 +696,7 @@
               buffer_context->GetGpuMemoryBuffer()->CloneHandle(),
               buffer_context->GetGpuMemoryBuffer()->GetSize(),
               buffer_context->GetGpuMemoryBuffer()->GetFormat(),
-              gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE,
-              base::DoNothing());
+              gfx::BufferUsage::SCANOUT_VEA_CPU_READ, base::DoNothing());
 
       media_task_runner_->PostTask(
           FROM_HERE,
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
index dac731ce..337304ca7 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
+++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -531,16 +531,6 @@
 crbug.com/1132627 external/wpt/css/css-flexbox/flex-aspect-ratio-img-column-011.html [ Failure ]
 crbug.com/721123 css3/flexbox/flexitem.html [ Failure ]
 crbug.com/721123 external/wpt/css/css-flexbox/flexitem-stretch-image.html [ Failure ]
-crbug.com/721123 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001.html [ Failure ]
-crbug.com/721123 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001v.html [ Failure ]
-crbug.com/721123 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002.html [ Failure ]
-crbug.com/721123 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002v.html [ Failure ]
-crbug.com/721123 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005.html [ Failure ]
-crbug.com/721123 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005v.html [ Failure ]
-crbug.com/721123 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006.html [ Failure ]
-crbug.com/721123 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006v.html [ Failure ]
-crbug.com/721123 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007.html [ Failure ]
-crbug.com/721123 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007v.html [ Failure ]
 crbug.com/704294 external/wpt/css/css-flexbox/flex-aspect-ratio-img-row-006.html [ Failure ]
 crbug.com/704294 external/wpt/css/css-flexbox/canvas-dynamic-change-001.html [ Failure ]
 crbug.com/987000 external/wpt/css/css-flexbox/flex-aspect-ratio-img-row-007.html [ Failure ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index fce73f0..98e1dfc 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -2205,8 +2205,13 @@
 # Remove from virtual tests when FontAccess is turned on by default.
 external/wpt/font-access/font_access-blob.tentative.https.window.html [ Skip ]
 external/wpt/font-access/font_access-enumeration.tentative.https.window.html [ Skip ]
+external/wpt/font-access/font_access-chooser.tentative.https.window.html [ Skip ]
 virtual/font-access/external/wpt/font-access/font_access-blob.tentative.https.window.html [ Pass ]
+virtual/font-access/external/wpt/font-access/font_access-chooser.tentative.https.window.html [ Skip ]
 virtual/font-access/external/wpt/font-access/font_access-enumeration.tentative.https.window.html [ Pass ]
+virtual/font-access-chooser/external/wpt/font-access/font_access-blob.tentative.https.window.html [ Skip ]
+virtual/font-access-chooser/external/wpt/font-access/font_access-chooser.tentative.https.window.html [ Pass ]
+virtual/font-access-chooser/external/wpt/font-access/font_access-enumeration.tentative.https.window.html [ Skip ]
 
 # text-orientation:upright
 crbug.com/1005518 external/wpt/css/css-writing-modes/table-progression-vlr-003.html [ Skip ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 429dd510..f594934 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -762,12 +762,6 @@
 crbug.com/1111128 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002b.html [ Failure ]
 crbug.com/1128262 external/wpt/css/css-flexbox/table-as-item-specified-width.html [ Failure ]
 
-# These are scheduled to deleted by mozilla. https://bugzilla.mozilla.org/show_bug.cgi?id=1664938
-crbug.com/704294 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003.html [ Failure ]
-crbug.com/704294 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003v.html [ Failure ]
-crbug.com/704294 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004.html [ Failure ]
-crbug.com/704294 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004v.html [ Failure ]
-
 crbug.com/249112 external/wpt/css/css-flexbox/flex-minimum-width-flex-items-007.xht [ Failure ]
 
 # These require css-align-3 positional keywords that Blink doesn't yet support for flexbox.
@@ -1189,7 +1183,6 @@
 
 ### Textarea NG
 crbug.com/1140307 accessibility/inline-text-textarea.html [ Failure ]
-crbug.com/1137666 editing/caret/caret-direction-auto.html [ Failure ]
 
 # ====== LayoutNG-only failures until here ======
 
@@ -1275,6 +1268,7 @@
 crbug.com/626703 external/wpt/css/css-text/text-transform/math/text-transform-math-sans-serif-001.tentative.html [ Failure ]
 crbug.com/1043295 [ Fuchsia ] virtual/font-access/external/wpt/font-access/font_access-blob.tentative.https.window.html [ Skip ]
 crbug.com/1043295 [ Fuchsia ] virtual/font-access/external/wpt/font-access/font_access-enumeration.tentative.https.window.html [ Skip ]
+crbug.com/1043295 [ Fuchsia ] virtual/font-access-chooser/external/wpt/font-access/font_access-chooser.tentative.https.window.html [ Skip ]
 
 # ====== Style team owned tests from here ======
 
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index c808aef..736ee90f 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -179,6 +179,11 @@
              "--mse-video-buffer-size-limit-mb=1"]
   },
   {
+    "prefix": "composite-bgcolor-animation",
+    "bases": ["external/wpt/css/composite-bgcolor-animation"],
+    "args": ["--enable-blink-features=CompositeBGColorAnimation"]
+  },
+  {
     "prefix": "composite-after-paint",
     "bases": ["compositing",
               "paint",
@@ -191,6 +196,11 @@
     "args": ["--enable-features=FontAccess"]
   },
   {
+    "prefix": "font-access-chooser",
+    "bases": ["external/wpt/font-access"],
+    "args": ["--enable-features=FontAccess,FontAccessChooser"]
+  },
+  {
     "prefix": "highdpi-threaded",
     "bases": ["external/wpt/css/css-paint-api/hidpi"],
     "args": ["--force-device-scale-factor=2",
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 3ae9ace..fbf7ba7 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -59558,19 +59558,6 @@
      ]
     },
     "css-flexbox": {
-     "Flexible-order.html": [
-      "9b61e1e8a8fd4cc41e461b10b86051ed0e536ef5",
-      [
-       null,
-       [
-        [
-         "/css/css-flexbox/reference/Flexible-order-ref.html",
-         "=="
-        ]
-       ],
-       {}
-      ]
-     ],
      "abspos-autopos-htb-ltr.html": [
       "095936edf8b982bc228316d1a4f449621e94a1c3",
       [
@@ -65163,6 +65150,19 @@
        {}
       ]
      ],
+     "flexible-order.html": [
+      "6f8d5f691a4be328999f375aa4ef940d01021e74",
+      [
+       null,
+       [
+        [
+         "/css/css-flexbox/reference/flexible-order-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "flexitem-stretch-range.html": [
       "43ecc81d52ddfbcf3d42ad2ed10577e851822636",
       [
@@ -148085,188 +148085,6 @@
           {}
          ]
         ],
-        "flexbox-intrinsic-ratio-001.html": [
-         "43d512dcdf3fa0d80adb4c59b6de303b095deea7",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
-        "flexbox-intrinsic-ratio-001v.html": [
-         "4cc910b9e289315b9b634d1eeec1ac77ba51957f",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
-        "flexbox-intrinsic-ratio-002.html": [
-         "229540ff445b5d3d9f398f59a3f0237348d54ae8",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
-        "flexbox-intrinsic-ratio-002v.html": [
-         "0df92f9954c14149d5e07a7ba362fd34249d6b6c",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
-        "flexbox-intrinsic-ratio-003.html": [
-         "cf1c7a74c7abe5ae7c5c1c20540a65435fae17cc",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
-        "flexbox-intrinsic-ratio-003v.html": [
-         "cb9275fd8cfdb2e17a46e31454b2799a3f1e44d0",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
-        "flexbox-intrinsic-ratio-004.html": [
-         "bf2912f04bc2ef2ff5e588710f6c81976664aa8d",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
-        "flexbox-intrinsic-ratio-004v.html": [
-         "01c5271c4556b2e3d43abbbb014482a4bab9740e",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
-        "flexbox-intrinsic-ratio-005.html": [
-         "fe7d806bcfee80331d9e9d071caa1bc672f50fe2",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
-        "flexbox-intrinsic-ratio-005v.html": [
-         "ed1dcace0f3385118af82726734778d6a74336eb",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
-        "flexbox-intrinsic-ratio-006.html": [
-         "764075c106b712686afc00188e5c40cad042646c",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
-        "flexbox-intrinsic-ratio-006v.html": [
-         "8c12fad8c791623a86ddca8936248189d698a0a4",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
-        "flexbox-intrinsic-ratio-007.html": [
-         "ea9179c32ca7916792132f4a73c159fca89a19b6",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
-        "flexbox-intrinsic-ratio-007v.html": [
-         "2efb8b1c18fa65c2ea4b08c2c797476bdc79273e",
-         [
-          null,
-          [
-           [
-            "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007-ref.html",
-            "=="
-           ]
-          ],
-          {}
-         ]
-        ],
         "flexbox-items-as-stacking-contexts-001.xhtml": [
          "fac905339110967578289f18ae156e4a651d81ab",
          [
@@ -160930,6 +160748,19 @@
          ],
          {}
         ]
+       ],
+       "padding-border-margin-002.html": [
+        "1ccfbb7005faeaeb66e584df2b9458cf2c30e805",
+        [
+         null,
+         [
+          [
+           "/mathml/relations/css-styling/padding-border-margin/padding-border-margin-002-ref.html",
+           "=="
+          ]
+         ],
+         {}
+        ]
        ]
       },
       "presentational-hints-001.html": [
@@ -182282,10 +182113,6 @@
       []
      ],
      "reference": {
-      "Flexible-order-ref.html": [
-       "12e94ba598e74cd253f0f91daf7e88f44884b7fc",
-       []
-      ],
       "align-baseline-ref.html": [
        "d5b88e8c7dae73b57c7f993260d7cce363eeebaa",
        []
@@ -182474,6 +182301,10 @@
        "0a8869a1452962b4895e60d8cebe987b55499666",
        []
       ],
+      "flexible-order-ref.html": [
+       "12e94ba598e74cd253f0f91daf7e88f44884b7fc",
+       []
+      ],
       "flexitem-stretch-range-ref.html": [
        "01c617698e26960960be4210fd726ce102e188bc",
        []
@@ -209650,30 +209481,6 @@
          "f9a4553ccbee361f31491dc91989d341ad9ac1d3",
          []
         ],
-        "flexbox-intrinsic-ratio-001-ref.html": [
-         "7441b282f4daf007e2876e72f257b093317d5854",
-         []
-        ],
-        "flexbox-intrinsic-ratio-003-ref.html": [
-         "38071c22fb2724d245dfe64e6fa17f0706d8a3c6",
-         []
-        ],
-        "flexbox-intrinsic-ratio-004-ref.html": [
-         "38e43a835eb07a322e0970b497fabc2a6f656628",
-         []
-        ],
-        "flexbox-intrinsic-ratio-005-ref.html": [
-         "2bfd4550c1d81c012a69a73cd871923f06d504c6",
-         []
-        ],
-        "flexbox-intrinsic-ratio-006-ref.html": [
-         "513fc0dcafacef04418c6bcd0d5121bdadea31f9",
-         []
-        ],
-        "flexbox-intrinsic-ratio-007-ref.html": [
-         "ccde6012b5f74ede005dad74814be62cdffa9ac6",
-         []
-        ],
         "flexbox-items-as-stacking-contexts-001-ref.xhtml": [
          "7e02b799f0f75b5d238ecc3c7bbaf87a53572e88",
          []
@@ -232249,37 +232056,13 @@
        []
       ],
       "mo-stretch-properties-dynamic-001-expected.txt": [
-       "d13682034cae987e5328fb75521120d8ab528a2f",
+       "6e33b9d6e7bf8417377f350beb8ae226cb65212c",
        []
       ],
       "operator-dictionary-combining-expected.txt": [
        "f338045a3e3e67ead37daae3436223edfb5f3ccb",
        []
       ],
-      "operator-dictionary-largeop-001-expected.txt": [
-       "ba4d95e79aae985c36ed54ca8d8c5a59b7f68dcb",
-       []
-      ],
-      "operator-dictionary-largeop-002-expected.txt": [
-       "ba4d95e79aae985c36ed54ca8d8c5a59b7f68dcb",
-       []
-      ],
-      "operator-dictionary-largeop-003-expected.txt": [
-       "ba4d95e79aae985c36ed54ca8d8c5a59b7f68dcb",
-       []
-      ],
-      "operator-dictionary-largeop-004-expected.txt": [
-       "ba4d95e79aae985c36ed54ca8d8c5a59b7f68dcb",
-       []
-      ],
-      "operator-dictionary-largeop-005-expected.txt": [
-       "ba4d95e79aae985c36ed54ca8d8c5a59b7f68dcb",
-       []
-      ],
-      "operator-dictionary-largeop-006-expected.txt": [
-       "ba4d95e79aae985c36ed54ca8d8c5a59b7f68dcb",
-       []
-      ],
       "operator-dictionary-stretchy-001-expected.txt": [
        "e554aa7810dbbb96899511c8a2e1ec7cb97d99a4",
        []
@@ -232618,6 +232401,10 @@
        "padding-border-margin-001-ref.html": [
         "150a650bc28434f1811d3d40747d074146ec4a30",
         []
+       ],
+       "padding-border-margin-002-ref.html": [
+        "e13a9f47ff4f68fd1486123735111079989165cf",
+        []
        ]
       },
       "presentational-hints-001-ref.html": [
@@ -370594,7 +370381,7 @@
      ]
     ],
     "input-events-get-target-ranges-backspace.tentative.html": [
-     "a67bc76364d9675f2048161544b26eee02bf1185",
+     "d057654a77c494934e1116045ec7541a7e8878da",
      [
       null,
       {
@@ -370613,7 +370400,7 @@
      ]
     ],
     "input-events-get-target-ranges-forwarddelete.tentative.html": [
-     "62a33c094000680bd5981f0e2e1cddb1a3c6c1f5",
+     "136a4a6be4b31fa79508104d8da42cce36d8a887",
      [
       null,
       {
@@ -372394,6 +372181,13 @@
         {}
        ]
       ],
+      "largeop-hit-testing.html": [
+       "4f6a7782f2797294b6f4ea3739df399312838101",
+       [
+        null,
+        {}
+       ]
+      ],
       "mo-axis-height-1.html": [
        "3b28d976f0cf999fe4fd1f684696823eaff47749",
        [
diff --git a/third_party/blink/web_tests/external/wpt/css/composite-bgcolor-animation/bg-color-with-gradient-ref.html b/third_party/blink/web_tests/external/wpt/css/composite-bgcolor-animation/bg-color-with-gradient-ref.html
new file mode 100644
index 0000000..5c76f34
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/composite-bgcolor-animation/bg-color-with-gradient-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<body>
+  <canvas id="canvas" width="100" height="100"></canvas>
+</body>
+<script>
+  var canvas = document.getElementById('canvas');
+  var ctx = canvas.getContext('2d');
+  var grad = ctx.createLinearGradient(0, 0, 0, 100);
+  grad.addColorStop(0, 'red');
+  grad.addColorStop(1, 'black');
+  ctx.fillStyle = grad;
+  ctx.fillRect(0, 0, 100, 100);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/composite-bgcolor-animation/bg-color-with-gradient.html b/third_party/blink/web_tests/external/wpt/css/composite-bgcolor-animation/bg-color-with-gradient.html
new file mode 100644
index 0000000..7ef5d61
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/composite-bgcolor-animation/bg-color-with-gradient.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-backgrounds-3/#background-color">
+<link rel="match" href="bg-color-with-gradient-ref.html">
+<div style="width: 100px; height: 100px; background: linear-gradient(red, black); background-color: green;"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/composite-bgcolor-animation/simple-bg-color-ref.html b/third_party/blink/web_tests/external/wpt/css/composite-bgcolor-animation/simple-bg-color-ref.html
new file mode 100644
index 0000000..d8003b5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/composite-bgcolor-animation/simple-bg-color-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+  <canvas id="canvas" width="200" height="400"></canvas>
+</body>
+<script>
+  var canvas = document.getElementById('canvas');
+  var ctx = canvas.getContext('2d');
+  ctx.fillStyle = 'green';
+  ctx.fillRect(0, 0, 100, 150);
+  ctx.fillStyle = 'red';
+  ctx.fillRect(0, 150, 200, 250);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/composite-bgcolor-animation/simple-bg-color.html b/third_party/blink/web_tests/external/wpt/css/composite-bgcolor-animation/simple-bg-color.html
new file mode 100644
index 0000000..07bea44
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/composite-bgcolor-animation/simple-bg-color.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-backgrounds-3/#background-color">
+<link rel="match" href="simple-bg-color-ref.html">
+<style>
+.box1 {
+  width: 100px;
+  height: 150px;
+  background-color: green;
+}
+.box2 {
+  width: 200px;
+  height: 250px;
+  background-color: red;
+}
+</style>
+<body>
+  <div class='box1'></div>
+  <div class='box2'></div>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/Flexible-order.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexible-order.html
similarity index 93%
rename from third_party/blink/web_tests/external/wpt/css/css-flexbox/Flexible-order.html
rename to third_party/blink/web_tests/external/wpt/css/css-flexbox/flexible-order.html
index 9b61e1e..6f8d5f6 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-flexbox/Flexible-order.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexible-order.html
@@ -4,7 +4,7 @@
 
 <meta name="assert" content="The order of three should be blue-red-black" />
 
-<link rel="match" href="reference/Flexible-order-ref.html">
+<link rel="match" href="reference/flexible-order-ref.html">
 <link rel="author" title="KeynesQu" href="mailto:keynesqu@sohu.com" />
 <link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#order-property" />
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/Flexible-order-ref.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/flexible-order-ref.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/Flexible-order-ref.html
rename to third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/flexible-order-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001-ref.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001-ref.html
deleted file mode 100644
index 7441b28..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001-ref.html
+++ /dev/null
@@ -1,122 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>CSS Reftest Reference</title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <style>
-      .flexbox {
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-        vertical-align: top;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 34px;
-                                              height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 34px;
-                                              height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 34px;
-                                              height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 34px;
-                                              height: 34px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 6px;
-                                              height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 6px;
-                                              height: 6px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001.html
deleted file mode 100644
index 43d512dc..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001.html
+++ /dev/null
@@ -1,125 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on non-stretched flex item w/ intrinsic ratio.
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-001-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: row;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: flex-start;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 0 0 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              max-height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 6px;
-                                              max-height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001v.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001v.html
deleted file mode 100644
index 4cc910b..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001v.html
+++ /dev/null
@@ -1,128 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on non-stretched flex item w/ intrinsic ratio
-      (with a vertical writing-mode on the flex items).
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-001-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: row;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: flex-start;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        writing-mode: vertical-lr;
-
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 0 0 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              max-height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 6px;
-                                              max-height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002.html
deleted file mode 100644
index 229540f..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002.html
+++ /dev/null
@@ -1,125 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on non-stretched flex item w/ intrinsic ratio.
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-001-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: column;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: flex-start;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 0 0 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              max-height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 6px;
-                                              max-height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002v.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002v.html
deleted file mode 100644
index 0df92f9..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002v.html
+++ /dev/null
@@ -1,128 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on non-stretched flex item w/ intrinsic ratio
-      (with a vertical writing-mode on the flex items).
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-001-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: column;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: flex-start;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        writing-mode: vertical-lr;
-
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 0 0 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              max-height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 6px;
-                                              max-height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003-ref.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003-ref.html
deleted file mode 100644
index 38071c2..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003-ref.html
+++ /dev/null
@@ -1,123 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>CSS Reftest Reference</title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <style>
-      .flexbox {
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-        vertical-align: top;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 16px;
-                                              height: 40px">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 40px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 34px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 34px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 34px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 34px;
-                                              height: 40px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 6px;
-                                              height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 6px;
-                                              height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 40px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 40px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003.html
deleted file mode 100644
index cf1c7a7..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003.html
+++ /dev/null
@@ -1,125 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on stretched flex item w/ intrinsic ratio.
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-003-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: row;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: stretch;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 0 0 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              max-height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 6px;
-                                              max-height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003v.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003v.html
deleted file mode 100644
index cb9275fd..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003v.html
+++ /dev/null
@@ -1,128 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on stretched flex item w/ intrinsic ratio
-      (with a vertical writing-mode on the flex items).
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-003-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: row;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: stretch;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        writing-mode: vertical-rl;
-
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 0 0 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              max-height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 6px;
-                                              max-height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004-ref.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004-ref.html
deleted file mode 100644
index 38e43a8..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004-ref.html
+++ /dev/null
@@ -1,123 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>CSS Reftest Reference</title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <style>
-      .flexbox {
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-        vertical-align: top;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 16px">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 34px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 6px;
-                                              height: 6px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004.html
deleted file mode 100644
index bf2912f0..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004.html
+++ /dev/null
@@ -1,125 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on stretched flex item w/ intrinsic ratio.
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-004-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: column;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: stretch;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 0 0 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              max-height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 6px;
-                                              max-height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004v.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004v.html
deleted file mode 100644
index 01c5271..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004v.html
+++ /dev/null
@@ -1,128 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on stretched flex item w/ intrinsic ratio
-      (with a vertical writing-mode on the flex items).
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-004-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: column;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: stretch;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        writing-mode: vertical-rl;
-
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 0 0 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              max-height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 6px;
-                                              max-height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005-ref.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005-ref.html
deleted file mode 100644
index 2bfd4550..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005-ref.html
+++ /dev/null
@@ -1,123 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>CSS Reftest Reference</title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <style>
-      .flexbox {
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-        vertical-align: top;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 6px;
-                                              height: 6px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005.html
deleted file mode 100644
index fe7d806..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005.html
+++ /dev/null
@@ -1,127 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on non-stretched flexible flex item w/ intrinsic ratio.
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-005-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: row;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: flex-start;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        flex: 1;
-
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 1 1 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              max-height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 6px;
-                                              max-height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005v.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005v.html
deleted file mode 100644
index ed1dcace..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005v.html
+++ /dev/null
@@ -1,129 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on non-stretched flexible flex item w/ intrinsic ratio
-      (with a vertical writing-mode on the flex items).
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-005-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: row;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: flex-start;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        flex: 1;
-        writing-mode: vertical-lr;
-
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 1 1 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              max-height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 6px;
-                                              max-height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006-ref.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006-ref.html
deleted file mode 100644
index 513fc0d..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006-ref.html
+++ /dev/null
@@ -1,123 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>CSS Reftest Reference</title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <style>
-      .flexbox {
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-        vertical-align: top;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 6px;
-                                              height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 6px;
-                                              height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 40px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 40px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 40px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 40px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006.html
deleted file mode 100644
index 764075c..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006.html
+++ /dev/null
@@ -1,127 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on non-stretched flexible flex item w/ intrinsic ratio.
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-006-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: column;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: flex-start;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        flex: 1;
-
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 1 1 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              max-height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 6px;
-                                              max-height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006v.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006v.html
deleted file mode 100644
index 8c12fad..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-006v.html
+++ /dev/null
@@ -1,129 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on non-stretched flexible flex item w/ intrinsic ratio
-      (with a vertical writing-mode on the flex items).
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-006-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: column;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: flex-start;
-
-        float: left; /* For testing in "rows" */
-      }
-      br { clear: both; }
-
-      .flexbox > * {
-        flex: 1;
-        writing-mode: vertical-lr;
-
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 1 1 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              max-height: 6px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 6px;
-                                              max-height: 10px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007-ref.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007-ref.html
deleted file mode 100644
index ccde6012..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007-ref.html
+++ /dev/null
@@ -1,128 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>CSS Reftest Reference</title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <style>
-      .flexbox {
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        float: left; /* For testing in "rows" */
-      }
-      img {
-        padding: 1px 2px 3px 4px;
-        box-sizing: border-box;
-        background: pink;
-      }
-
-      br { clear: both; }
-
-      .flexbox > * {
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-        vertical-align: top;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 28px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 32px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 28px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 34px;
-                                              height: 32px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 36px;
-                                              height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 36px;
-                                              height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 34px;
-                                              height: 32px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 16px;
-                                              height: 14px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 18px;
-                                              height: 16px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 16px;
-                                              height: 14px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 14px;
-                                              height: 12px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007.html
deleted file mode 100644
index ea9179c3..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007.html
+++ /dev/null
@@ -1,132 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on non-stretched flex item w/ intrinsic ratio,
-      some padding, and box-sizing:border-box.
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-007-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: row;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: flex-start;
-
-        float: left; /* For testing in "rows" */
-      }
-      img {
-        padding: 1px 2px 3px 4px;
-        box-sizing: border-box;
-        background: pink;
-      }
-
-      br { clear: both; }
-
-      .flexbox > * {
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 0 0 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 16px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 16px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 20px;
-                                              max-height: 14px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 14px;
-                                              max-height: 20px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007v.html b/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007v.html
deleted file mode 100644
index 2efb8b1c..0000000
--- a/third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-007v.html
+++ /dev/null
@@ -1,134 +0,0 @@
-<!DOCTYPE html>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>
-      CSS Test: Testing how explicit main-size & cross-size constraints
-      influence sizing on non-stretched flex item w/ intrinsic ratio,
-      some padding, box-sizing:border-box, and a vertical writing-mode.
-    </title>
-    <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-main-size">
-    <link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size">
-    <link rel="match" href="flexbox-intrinsic-ratio-007-ref.html">
-    <style>
-      .flexbox {
-        display: flex;
-        flex-direction: row;
-        border: 1px solid black;
-        margin: 0 2px 2px 0; /* (Just for spacing things out, visually) */
-        width: 40px;
-        height: 40px;
-
-        justify-content: flex-start;
-        align-items: flex-start;
-
-        float: left; /* For testing in "rows" */
-      }
-      img {
-        padding: 1px 2px 3px 4px;
-        box-sizing: border-box;
-        background: pink;
-      }
-
-      br { clear: both; }
-
-      .flexbox > * {
-        writing-mode: vertical-lr;
-
-        /* Disable "min-width:auto"/"min-height:auto" to focus purely on
-           later channels of influence. */
-        min-width: 0;
-        min-height: 0;
-      }
-    </style>
-  </head>
-  <body>
-    <!-- NOTE: solidblue.png has an intrinsic size of 16px by 16px. -->
-
-    <!-- Row 1: no special sizing: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png">
-    </div>
-    <br>
-
-    <!-- Row 2: Specified main-size, cross-size, or flex-basis: -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="flex: 0 0 30px">
-    </div>
-    <br>
-
-    <!-- Row 3: min main-size OR min cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              min-height: 34px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 34px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 4: max main-size OR max cross-size, or both -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 16px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-height: 16px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 20px;
-                                              max-height: 14px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 14px;
-                                              max-height: 20px">
-    </div>
-    <br>
-
-    <!-- Row 5: min main-size vs. max cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              min-height: 30px">
-    </div>
-    <br>
-
-    <!-- Row 6: min|max main-size vs. explicit cross-size, & vice versa -->
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="min-width: 30px;
-                                              height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 30px;
-                                              max-height: 10px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="max-width: 10px;
-                                              height: 30px">
-    </div>
-    <div class="flexbox">
-      <img src="support/solidblue.png" style="width: 10px;
-                                              min-height: 30px">
-    </div>
-  </body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/font-access/font_access-chooser.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/font-access/font_access-chooser.tentative.https.window.js
new file mode 100644
index 0000000..047521a7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/font-access/font_access-chooser.tentative.https.window.js
@@ -0,0 +1,4 @@
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=resources/test-expectations.js
+// META: script=resources/window-tests-chooser.js
diff --git a/third_party/blink/web_tests/external/wpt/font-access/resources/window-tests-chooser.js b/third_party/blink/web_tests/external/wpt/font-access/resources/window-tests-chooser.js
new file mode 100644
index 0000000..bb9e0bf1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/font-access/resources/window-tests-chooser.js
@@ -0,0 +1,8 @@
+'use strict';
+
+font_access_test(async t => {
+  await promise_rejects_dom(
+      t, 'NotSupportedError', navigator.fonts.showFontChooser());
+  await promise_rejects_dom(
+      t, 'NotSupportedError', navigator.fonts.showFontChooser({all: false}));
+});
diff --git a/third_party/blink/web_tests/external/wpt/input-events/input-events-get-target-ranges-backspace.tentative.html b/third_party/blink/web_tests/external/wpt/input-events/input-events-get-target-ranges-backspace.tentative.html
index a67bc763..d057654a 100644
--- a/third_party/blink/web_tests/external/wpt/input-events/input-events-get-target-ranges-backspace.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/input-events/input-events-get-target-ranges-backspace.tentative.html
@@ -1169,6 +1169,78 @@
   checkGetTargetRangesOfInputOnDoNothing();
 }, 'Backspace at "<p>abc</p><table><caption>{}<br></caption><tr><td>cell</td></tr></table>"');
 
+// If a table cell element is selected, only its content should be deleted.
+promise_test(async () => {
+  initializeTest("<table><tr><td>cell1</td><td>cell2</td></tr></table>");
+  let cell1 = gEditor.querySelector("td");
+  let tr = cell1.parentNode;
+  gSelection.setBaseAndExtent(tr, 0, tr, 1);
+  await sendBackspaceKey();
+  assert_in_array(gEditor.innerHTML, ["<table><tbody><tr><td></td><td>cell2</td></tr></tbody></table>",
+                                      "<table><tbody><tr><td><br></td><td>cell2</td></tr></tbody></table>"]);
+  // XXX Perhaps, target range should be selecting only all children of
+  //     cell1 instead.
+  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
+    startContainer: tr,
+    startOffset: 0,
+    endContainer: tr,
+    endOffset: 1,
+  });
+  checkGetTargetRangesOfInputOnDeleteSomething();
+}, 'Backspace at "<table><tr>{<td>cell1</td>}<td>cell2</td></tr></table>"');
+
+promise_test(async () => {
+  initializeTest("<table><tr><td>cell1</td><td>cell2</td></tr></table>");
+  let cell2 = gEditor.querySelector("td + td");
+  let tr = cell2.parentNode;
+  gSelection.setBaseAndExtent(tr, 1, tr, 2);
+  await sendBackspaceKey();
+  assert_in_array(gEditor.innerHTML, ["<table><tbody><tr><td>cell1</td><td></td></tr></tbody></table>",
+                                      "<table><tbody><tr><td>cell1</td><td><br></td></tr></tbody></table>"]);
+  // XXX Perhaps, target range should be selecting only all children of
+  //     cell1 instead.
+  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
+    startContainer: tr,
+    startOffset: 1,
+    endContainer: tr,
+    endOffset: 2,
+  });
+  checkGetTargetRangesOfInputOnDeleteSomething();
+}, 'Backspace at "<table><tr><td>cell1</td>{<td>cell2</td>}</tr></table>"');
+
+// If the last table cell element is selected, what browsers should do?
+promise_test(async () => {
+  initializeTest("<table><tr><td>cell</td></tr></table>");
+  let cell = gEditor.querySelector("td");
+  let tr = cell.parentNode;
+  let table = gEditor.querySelector("table");
+  gSelection.setBaseAndExtent(tr, 0, tr, 1);
+  await sendBackspaceKey();
+  assert_in_array(gEditor.innerHTML, ["<table><tbody><tr><td></td></tr></tbody></table>",
+                                      "<table><tbody><tr><td><br></td></tr></tbody></table>",
+                                      "<br>"]);
+  if (gEditor.querySelector("table")) {
+    // XXX Perhaps, target range should be selecting only all children of
+    //     cell1 instead.
+    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
+      startContainer: tr,
+      startOffset: 0,
+      endContainer: tr,
+      endOffset: 1,
+    });
+  } else {
+    // If it causes deleting entire the table, the `<table>` element should
+    // be in the target range.
+    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
+      startContainer: gEditor,
+      startOffset: 0,
+      endContainer: gEditor,
+      endOffset: 1,
+    });
+  }
+  checkGetTargetRangesOfInputOnDeleteSomething();
+}, 'Backspace at "<table><tr>{<td>cell</td>}</tr></table>"');
+
 // If caret is not adjacent of deleting character, browser may not delete the
 // character, but update the caret position for next deletion.
 promise_test(async () => {
diff --git a/third_party/blink/web_tests/external/wpt/input-events/input-events-get-target-ranges-forwarddelete.tentative.html b/third_party/blink/web_tests/external/wpt/input-events/input-events-get-target-ranges-forwarddelete.tentative.html
index 62a33c094..136a4a6b 100644
--- a/third_party/blink/web_tests/external/wpt/input-events/input-events-get-target-ranges-forwarddelete.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/input-events/input-events-get-target-ranges-forwarddelete.tentative.html
@@ -1286,6 +1286,78 @@
   checkGetTargetRangesOfInputOnDoNothing();
 }, 'Delete at "<table><caption>{}<br></caption><tr><td>cell</td></tr></table>"');
 
+// If a table cell element is selected, only its content should be deleted.
+promise_test(async () => {
+  initializeTest("<table><tr><td>cell1</td><td>cell2</td></tr></table>");
+  let cell1 = gEditor.querySelector("td");
+  let tr = cell1.parentNode;
+  gSelection.setBaseAndExtent(tr, 0, tr, 1);
+  await sendDeleteKey();
+  assert_in_array(gEditor.innerHTML, ["<table><tbody><tr><td></td><td>cell2</td></tr></tbody></table>",
+                                      "<table><tbody><tr><td><br></td><td>cell2</td></tr></tbody></table>"]);
+  // XXX Perhaps, target range should be selecting only all children of
+  //     cell1 instead.
+  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
+    startContainer: tr,
+    startOffset: 0,
+    endContainer: tr,
+    endOffset: 1,
+  });
+  checkGetTargetRangesOfInputOnDeleteSomething();
+}, 'Delete at "<table><tr>{<td>cell1</td>}<td>cell2</td></tr></table>"');
+
+promise_test(async () => {
+  initializeTest("<table><tr><td>cell1</td><td>cell2</td></tr></table>");
+  let cell2 = gEditor.querySelector("td + td");
+  let tr = cell2.parentNode;
+  gSelection.setBaseAndExtent(tr, 1, tr, 2);
+  await sendDeleteKey();
+  assert_in_array(gEditor.innerHTML, ["<table><tbody><tr><td>cell1</td><td></td></tr></tbody></table>",
+                                      "<table><tbody><tr><td>cell1</td><td><br></td></tr></tbody></table>"]);
+  // XXX Perhaps, target range should be selecting only all children of
+  //     cell1 instead.
+  checkGetTargetRangesOfBeforeinputOnDeleteSomething({
+    startContainer: tr,
+    startOffset: 1,
+    endContainer: tr,
+    endOffset: 2,
+  });
+  checkGetTargetRangesOfInputOnDeleteSomething();
+}, 'Delete at "<table><tr><td>cell1</td>{<td>cell2</td>}</tr></table>"');
+
+// If the last table cell element is selected, what browsers should do?
+promise_test(async () => {
+  initializeTest("<table><tr><td>cell</td></tr></table>");
+  let cell = gEditor.querySelector("td");
+  let tr = cell.parentNode;
+  let table = gEditor.querySelector("table");
+  gSelection.setBaseAndExtent(tr, 0, tr, 1);
+  await sendDeleteKey();
+  assert_in_array(gEditor.innerHTML, ["<table><tbody><tr><td></td></tr></tbody></table>",
+                                      "<table><tbody><tr><td><br></td></tr></tbody></table>",
+                                      "<br>"]);
+  if (gEditor.querySelector("table")) {
+    // XXX Perhaps, target range should be selecting only all children of
+    //     cell1 instead.
+    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
+      startContainer: tr,
+      startOffset: 0,
+      endContainer: tr,
+      endOffset: 1,
+    });
+  } else {
+    // If it causes deleting entire the table, the `<table>` element should
+    // be in the target range.
+    checkGetTargetRangesOfBeforeinputOnDeleteSomething({
+      startContainer: gEditor,
+      startOffset: 0,
+      endContainer: gEditor,
+      endOffset: 1,
+    });
+  }
+  checkGetTargetRangesOfInputOnDeleteSomething();
+}, 'Delete at "<table><tr>{<td>cell</td>}</tr></table>"');
+
 // If caret is not adjacent of deleting character, browser may not delete the
 // character, but update the caret position for next deletion.
 promise_test(async () => {
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-trusted-types-policy-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-trusted-types-policy-expected.txt
new file mode 100644
index 0000000..d8f291f
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-trusted-types-policy-expected.txt
@@ -0,0 +1,20 @@
+Verify that Trusted Types policy violation issue is generated.
+
+Inspector issue: {
+    issue : {
+        code : ContentSecurityPolicyIssue
+        details : {
+            contentSecurityPolicyIssueDetails : {
+                contentSecurityPolicyViolationType : kTrustedTypesPolicyViolation
+                isReportOnly : false
+                sourceCodeLocation : {
+                    columnNumber : 36
+                    lineNumber : 4
+                    url : https://devtools.test:8443/inspector-protocol/resources/content-security-policy-issue-trusted-types-policy.php
+                }
+                violatedDirective : trusted-types
+            }
+        }
+    }
+}
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-trusted-types-policy.js b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-trusted-types-policy.js
new file mode 100644
index 0000000..399f6289
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-trusted-types-policy.js
@@ -0,0 +1,12 @@
+(async function(testRunner) {
+    const {page, session, dp} = await testRunner.startBlank(
+      `Verify that Trusted Types policy violation issue is generated.\n`);
+
+    await dp.Network.enable();
+    await dp.Audits.enable();
+    page.navigate('https://devtools.test:8443/inspector-protocol/resources/content-security-policy-issue-trusted-types-policy.php');
+    const issue = await dp.Audits.onceIssueAdded();
+
+    testRunner.log(issue.params, "Inspector issue: ");
+    testRunner.completeTest();
+  })
\ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-trusted-types-sink-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-trusted-types-sink-expected.txt
new file mode 100644
index 0000000..27562f1
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-trusted-types-sink-expected.txt
@@ -0,0 +1,20 @@
+Verify that Trusted Types sink violation issue is generated.
+
+Inspector issue: {
+    issue : {
+        code : ContentSecurityPolicyIssue
+        details : {
+            contentSecurityPolicyIssueDetails : {
+                contentSecurityPolicyViolationType : kTrustedTypesSinkViolation
+                isReportOnly : false
+                sourceCodeLocation : {
+                    columnNumber : 55
+                    lineNumber : 5
+                    url : https://devtools.test:8443/inspector-protocol/resources/content-security-policy-issue-trusted-types-sink.php
+                }
+                violatedDirective : require-trusted-types-for
+            }
+        }
+    }
+}
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-trusted-types-sink.js b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-trusted-types-sink.js
new file mode 100644
index 0000000..7a75dcc3
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-trusted-types-sink.js
@@ -0,0 +1,12 @@
+(async function(testRunner) {
+    const {page, session, dp} = await testRunner.startBlank(
+      `Verify that Trusted Types sink violation issue is generated.\n`);
+
+    await dp.Network.enable();
+    await dp.Audits.enable();
+    page.navigate('https://devtools.test:8443/inspector-protocol/resources/content-security-policy-issue-trusted-types-sink.php');
+    const issue = await dp.Audits.onceIssueAdded();
+
+    testRunner.log(issue.params, "Inspector issue: ");
+    testRunner.completeTest();
+  })
\ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/content-security-policy-issue-trusted-types-policy.php b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/content-security-policy-issue-trusted-types-policy.php
new file mode 100644
index 0000000..c32d70e5
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/content-security-policy-issue-trusted-types-policy.php
@@ -0,0 +1,13 @@
+<?php
+header("Content-Security-Policy: require-trusted-types-for 'script'; trusted-types policy1");
+?>
+<!DOCTYPE html>
+<html>
+  <body>
+    <script>
+      const policy2 = trustedTypes.createPolicy("policy2", {
+        createHTML: string => string,
+      });
+    </script>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/content-security-policy-issue-trusted-types-sink.php b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/content-security-policy-issue-trusted-types-sink.php
new file mode 100644
index 0000000..13167b76
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/content-security-policy-issue-trusted-types-sink.php
@@ -0,0 +1,12 @@
+<?php
+header("Content-Security-Policy: require-trusted-types-for 'script';");
+?>
+<!DOCTYPE html>
+<html>
+  <body>
+    <div id="exampleDiv"></div>
+    <script>
+      document.getElementById("exampleDiv").innerHTML = "foo";
+    </script>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index d7e43ce..6b3846b 100644
--- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -3921,6 +3921,7 @@
     method constructor
     method releaseLock
     method write
+[NAMESPACES]
 [GLOBAL OBJECT]
     attribute console
     attribute globalThis
diff --git a/third_party/blink/web_tests/platform/linux/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
index 4a6572b..a346b23 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
@@ -6,6 +6,7 @@
 interface Navigator
 interface Notification : EventTarget
     getter image
+[NAMESPACES]
 [GLOBAL OBJECT]
 PASS successfullyParsed is true
 
diff --git a/third_party/blink/web_tests/platform/mac/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
index 91ae335..3af5376 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
@@ -80,6 +80,7 @@
 interface Navigator
     getter bluetooth
 interface Notification : EventTarget
+[NAMESPACES]
 [GLOBAL OBJECT]
 PASS successfullyParsed is true
 
diff --git a/third_party/blink/web_tests/platform/win/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt b/third_party/blink/web_tests/platform/win/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
index 6bc3880..5f01f4b0 100644
--- a/third_party/blink/web_tests/platform/win/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
+++ b/third_party/blink/web_tests/platform/win/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
@@ -81,6 +81,7 @@
     getter bluetooth
 interface Notification : EventTarget
     getter image
+[NAMESPACES]
 [GLOBAL OBJECT]
 PASS successfullyParsed is true
 
diff --git a/third_party/blink/web_tests/platform/win7/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
index 4a6572b..a346b23 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
+++ b/third_party/blink/web_tests/platform/win7/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
@@ -6,6 +6,7 @@
 interface Navigator
 interface Notification : EventTarget
     getter image
+[NAMESPACES]
 [GLOBAL OBJECT]
 PASS successfullyParsed is true
 
diff --git a/third_party/blink/web_tests/resources/global-interface-listing.js b/third_party/blink/web_tests/resources/global-interface-listing.js
index 89bd8c3..0163a9a 100644
--- a/third_party/blink/web_tests/resources/global-interface-listing.js
+++ b/third_party/blink/web_tests/resources/global-interface-listing.js
@@ -77,7 +77,7 @@
     'unescape',
 ]);
 
-function isWebIDLConstructor(propertyKey) {
+function isWebIDLInterface(propertyKey) {
     if (jsBuiltins.has(propertyKey))
         return false;
     var descriptor = Object.getOwnPropertyDescriptor(this, propertyKey);
@@ -86,6 +86,18 @@
     return descriptor.writable && !descriptor.enumerable && descriptor.configurable;
 }
 
+function isWebIDLNamespace(propertyKey) {
+    if (jsBuiltins.has(propertyKey))
+        return false;
+    let object = Object.getOwnPropertyDescriptor(this, propertyKey).value;
+    if (object == undefined || typeof(object) != 'object' ||
+        object.prototype != undefined) {
+        return false;
+    }
+    let classString = Object.getOwnPropertyDescriptor(object, Symbol.toStringTag);
+    return classString && classString.value == propertyKey;
+}
+
 var wellKnownSymbols = new Map([
     [Symbol.asyncIterator, "@@asyncIterator"],
     [Symbol.hasInstance, "@@hasInstance"],
@@ -192,13 +204,7 @@
     outputFunc('    ' + property);
 }
 
-// FIXME: List interfaces with LegacyNoInterfaceObject specified in their IDL file.
-outputFunc('[INTERFACES]');
-var interfaceNames = Object.getOwnPropertyNames(this)
-                           .filter(isWebIDLConstructor)
-                           .filter(filterPlatformSpecificInterface);
-interfaceNames.sort();
-interfaceNames.forEach(function(interfaceName) {
+function outputWebIDLInterface(interfaceName) {
     var inheritsFrom = this[interfaceName].__proto__.name;
     if (inheritsFrom)
         outputFunc('interface ' + interfaceName + ' : ' + inheritsFrom);
@@ -215,12 +221,40 @@
         propertyStrings.filter((property) => filterPlatformSpecificProperty(interfaceName, property))
             .sort().forEach(outputProperty);
     });
-});
+}
+
+function outputWebIDLNamespace(namespaceName) {
+    outputFunc('namespace ' + namespaceName);
+    let object = this[namespaceName];
+    let propertyKeys = collectPropertyKeys(object);
+    let propertyStrings = [];
+    propertyKeys.forEach((propertyKey) => {
+        collectPropertyInfo(object, propertyKey, propertyStrings);
+    });
+
+    propertyStrings.sort().forEach(outputProperty);
+}
+
+outputFunc('[INTERFACES]');
+var interfaceNames = Object.getOwnPropertyNames(this)
+                           .filter(isWebIDLInterface)
+                           .filter(filterPlatformSpecificInterface);
+interfaceNames.sort();
+interfaceNames.forEach(outputWebIDLInterface);
+
+outputFunc('[NAMESPACES]');
+let namespaceNames = Object.getOwnPropertyNames(this)
+                           .filter(isWebIDLNamespace)
+                           .filter(filterPlatformSpecificInterface);
+namespaceNames.sort();
+namespaceNames.forEach(outputWebIDLNamespace);
 
 outputFunc('[GLOBAL OBJECT]');
 var propertyStrings = [];
 var memberNames = propertyNamesInGlobal.filter(function(propertyKey) {
-    return !jsBuiltins.has(propertyKey) && !isWebIDLConstructor(propertyKey);
+    return !jsBuiltins.has(propertyKey)
+        && !isWebIDLInterface(propertyKey)
+        && !isWebIDLNamespace(propertyKey);
 });
 memberNames.forEach(function(propertyKey) {
     collectPropertyInfo(globalObject, propertyKey, propertyStrings);
diff --git a/third_party/blink/web_tests/virtual/composite-bgcolor-animation/external/wpt/css/composite-bgcolor-animation/README.txt b/third_party/blink/web_tests/virtual/composite-bgcolor-animation/external/wpt/css/composite-bgcolor-animation/README.txt
new file mode 100644
index 0000000..54b46bd
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/composite-bgcolor-animation/external/wpt/css/composite-bgcolor-animation/README.txt
@@ -0,0 +1,2 @@
+# This suite runs the test in external/wpt/css/composite-bg-color-animation with
+# --enable-blink-features=CompositeBGColorAnimation
diff --git a/third_party/blink/web_tests/virtual/font-access-chooser/OWNERS b/third_party/blink/web_tests/virtual/font-access-chooser/OWNERS
new file mode 100644
index 0000000..272a4ab
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/font-access-chooser/OWNERS
@@ -0,0 +1 @@
+file://third_party/blink/renderer/modules/font_access/OWNERS
diff --git a/third_party/blink/web_tests/virtual/font-access-chooser/README.md b/third_party/blink/web_tests/virtual/font-access-chooser/README.md
new file mode 100644
index 0000000..57f1a91
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/font-access-chooser/README.md
@@ -0,0 +1 @@
+# This suite runs tests with --enable-features=FontAccess,FontAccessChooser
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 590316cd..f475c57b 100644
--- a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -2749,6 +2749,7 @@
     method constructor
     method releaseLock
     method write
+[NAMESPACES]
 [GLOBAL OBJECT]
     attribute console
     attribute globalThis
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
index f3bec20..420ea7a 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -2794,6 +2794,7 @@
 [Worker] interface XMLHttpRequestUpload : XMLHttpRequestEventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
+[Worker] [NAMESPACES]
 [Worker] [GLOBAL OBJECT]
 [Worker]     attribute console
 [Worker]     attribute globalThis
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
index 90b779be..dc2aeea 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -9558,6 +9558,7 @@
     setter protocol
     setter search
     setter username
+[NAMESPACES]
 [GLOBAL OBJECT]
     attribute GCController
     attribute accessibilityController
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
index 6b2a8588..b95ca1c7 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -2681,6 +2681,7 @@
 [Worker] interface XMLHttpRequestUpload : XMLHttpRequestEventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
+[Worker] [NAMESPACES]
 [Worker] [GLOBAL OBJECT]
 [Worker]     attribute console
 [Worker]     attribute globalThis
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index d771389..36031eca 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -4071,6 +4071,7 @@
 [Worker] interface XMLHttpRequestUpload : XMLHttpRequestEventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
+[Worker] [NAMESPACES]
 [Worker] [GLOBAL OBJECT]
 [Worker]     attribute console
 [Worker]     attribute globalThis
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 d147088..8ae23d75 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
@@ -11752,6 +11752,7 @@
     setter protocol
     setter search
     setter username
+[NAMESPACES]
 [GLOBAL OBJECT]
     attribute GCController
     attribute accessibilityController
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-platform-specific-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-platform-specific-expected.txt
index 968ca0f..0e40791 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-platform-specific-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-platform-specific-expected.txt
@@ -89,6 +89,7 @@
     getter bluetooth
 interface Notification : EventTarget
     getter image
+[NAMESPACES]
 [GLOBAL OBJECT]
 PASS successfullyParsed is true
 
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
index 159bf2d..ec14412 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -3842,6 +3842,7 @@
 [Worker] interface XMLHttpRequestUpload : XMLHttpRequestEventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
+[Worker] [NAMESPACES]
 [Worker] [GLOBAL OBJECT]
 [Worker]     attribute console
 [Worker]     attribute globalThis
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 5d5578de..fa55c84 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -30005,6 +30005,7 @@
   <int value="3706" label="UnicodeBidiPlainText"/>
   <int value="3707" label="ColorSchemeDarkSupportedOnRoot"/>
   <int value="3708" label="WebBluetoothGetAvailability"/>
+  <int value="3709" label="DigitalGoodsListPurchases"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
@@ -65704,7 +65705,7 @@
 <enum name="ServiceWorkerInstalledScriptsManager.FinishedReason">
   <int value="0" label="NOT_FINISHED"/>
   <int value="1" label="SUCCESS"/>
-  <int value="2" label="NO_HTTP_INFO_ERROR"/>
+  <int value="2" label="NO_RESPONSE_HEAD_ERROR"/>
   <int value="3" label="CREATE_DATA_PIPE_ERROR"/>
   <int value="4" label="CONNECTION_ERROR"/>
   <int value="5" label="RESPONSE_READER_ERROR"/>
diff --git a/tools/metrics/histograms/histograms_xml/cras/histograms.xml b/tools/metrics/histograms/histograms_xml/cras/histograms.xml
index 2c0d8188..90d2388 100644
--- a/tools/metrics/histograms/histograms_xml/cras/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/cras/histograms.xml
@@ -21,7 +21,7 @@
 
 <histograms>
 
-<histogram name="Cras.Busyloop" units="units" expires_after="2021-02-14">
+<histogram name="Cras.Busyloop" units="units" expires_after="2021-12-01">
 <!-- Name completed by histogram_suffixes
      name="Cras.TimePeriod" -->
 
@@ -37,7 +37,7 @@
   </summary>
 </histogram>
 
-<histogram name="Cras.BusyloopLength" units="units" expires_after="2021-06-16">
+<histogram name="Cras.BusyloopLength" units="units" expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -47,7 +47,7 @@
 </histogram>
 
 <histogram name="Cras.DeviceTypeInput" enum="CrasDeviceType"
-    expires_after="2021-04-04">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -58,7 +58,7 @@
 </histogram>
 
 <histogram name="Cras.DeviceTypeOutput" enum="CrasDeviceType"
-    expires_after="2021-04-18">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -68,7 +68,7 @@
   </summary>
 </histogram>
 
-<histogram name="Cras.DeviceVolume" units="level" expires_after="2021-07-22">
+<histogram name="Cras.DeviceVolume" units="level" expires_after="2021-12-01">
 <!-- Name completed by histogram_suffixes
      name="Cras.DeviceType" -->
 
@@ -80,7 +80,7 @@
 </histogram>
 
 <histogram name="Cras.HfpBatteryIndicatorSupported"
-    enum="CrasHfpBatteryIndicator" expires_after="2021-04-11">
+    enum="CrasHfpBatteryIndicator" expires_after="2021-12-01">
   <owner>enshuo@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -89,7 +89,7 @@
 </histogram>
 
 <histogram name="Cras.HfpBatteryReport" enum="CrasHfpBatteryIndicator"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>enshuo@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -101,7 +101,7 @@
 </histogram>
 
 <histogram name="Cras.HfpScoConnectionError" enum="CrasHfpScoError"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>enshuo@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -111,7 +111,7 @@
 </histogram>
 
 <histogram name="Cras.HfpWidebandSpeechPacketLoss" units="units"
-    expires_after="2021-04-04">
+    expires_after="2021-12-01">
   <owner>enshuo@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -122,7 +122,7 @@
 </histogram>
 
 <histogram name="Cras.HfpWidebandSpeechSupported" units="BooleanSupported"
-    expires_after="2021-04-18">
+    expires_after="2021-12-01">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -132,7 +132,7 @@
 </histogram>
 
 <histogram name="Cras.HighestDeviceDelayInput" units="units"
-    expires_after="2021-02-21">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -145,7 +145,7 @@
 </histogram>
 
 <histogram name="Cras.HighestDeviceDelayOutput" units="units"
-    expires_after="2021-02-21">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -158,7 +158,7 @@
 </histogram>
 
 <histogram name="Cras.HighestInputHardwareLevel" units="frames"
-    expires_after="2021-02-21">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -169,7 +169,7 @@
 </histogram>
 
 <histogram name="Cras.HighestOutputHardwareLevel" units="frames"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -180,7 +180,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceA2DPRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -191,7 +191,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceAbnormalFallbackRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -202,7 +202,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceBluetoothNarrowBandMicRuntime" units="seconds"
-    expires_after="2021-02-21">
+    expires_after="2021-12-01">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -213,7 +213,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceBluetoothRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -225,7 +225,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceBluetoothWideBandMicRuntime" units="seconds"
-    expires_after="2021-04-04">
+    expires_after="2021-12-01">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -236,7 +236,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceFrontMicRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -247,7 +247,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceHFPRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -258,7 +258,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceHotwordRuntime" units="seconds"
-    expires_after="2021-02-21">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -269,7 +269,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceHSPRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -280,7 +280,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceInternalMicRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -291,7 +291,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceKeyboardMicRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -302,7 +302,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceMicRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -313,7 +313,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceNormalFallbackRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -324,7 +324,7 @@
 </histogram>
 
 <histogram name="Cras.InputDevicePostDspLoopbackRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -335,7 +335,7 @@
 </histogram>
 
 <histogram name="Cras.InputDevicePostMixLoopbackRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -346,7 +346,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceRearMicRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -357,7 +357,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceSilentHotwordRuntime" units="seconds"
-    expires_after="2021-03-15">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -368,7 +368,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceUnknownRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -379,7 +379,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceUSBRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -390,7 +390,7 @@
 </histogram>
 
 <histogram name="Cras.InputStreamRuntime" units="seconds"
-    expires_after="2021-02-21">
+    expires_after="2021-12-01">
 <!-- Name completed by histogram_suffixes
      name="Cras.ClientType" -->
 
@@ -404,7 +404,7 @@
 </histogram>
 
 <histogram name="Cras.kHfpWidebandSpeechSelectedCodec" enum="CrasHfpCodec"
-    expires_after="2021-04-18">
+    expires_after="2021-12-01">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -414,7 +414,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackFirstTimeInput" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -428,7 +428,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackFirstTimeOutput" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -442,7 +442,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackFrequencyAfterReschedulingInput"
-    units="count" expires_after="2020-12-01">
+    units="count" expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -453,7 +453,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackFrequencyAfterReschedulingOutput"
-    units="count" expires_after="2020-12-01">
+    units="count" expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -465,7 +465,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackFrequencyInput" units="count"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -476,7 +476,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackFrequencyOutput" units="count"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -487,7 +487,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackSecondTimeInput" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -498,7 +498,7 @@
 </histogram>
 
 <histogram name="Cras.MissedCallbackSecondTimeOutput" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -509,7 +509,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceA2DPRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -520,7 +520,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceAbnormalFallbackRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -531,7 +531,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceBluetoothRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -543,7 +543,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceHapticRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -554,7 +554,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceHDMIRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -565,7 +565,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceHeadphoneRuntime" units="seconds"
-    expires_after="2021-02-07">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -576,7 +576,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceHFPRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -587,7 +587,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceHSPRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -598,7 +598,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceInternalSpeakerRuntime" units="seconds"
-    expires_after="2021-01-31">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -609,7 +609,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceLineoutRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -620,7 +620,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceNormalFallbackRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -631,7 +631,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceUnknownRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -642,7 +642,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceUSBRuntime" units="seconds"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -653,7 +653,7 @@
 </histogram>
 
 <histogram name="Cras.OutputStreamRuntime" units="seconds"
-    expires_after="2021-02-21">
+    expires_after="2021-12-01">
 <!-- Name completed by histogram_suffixes
      name="Cras.ClientType" -->
 
@@ -667,7 +667,7 @@
 </histogram>
 
 <histogram name="Cras.StreamCallbackThreshold" units="frames"
-    expires_after="2021-04-04">
+    expires_after="2021-12-01">
 <!-- Name completed by histogram_suffixes
      name="Cras.Direction" and
      name="Cras.ClientType" -->
@@ -682,7 +682,7 @@
 </histogram>
 
 <histogram name="Cras.StreamClientTypeInput" enum="CrasClientType"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -692,7 +692,7 @@
 </histogram>
 
 <histogram name="Cras.StreamClientTypeOutput" enum="CrasClientType"
-    expires_after="2020-12-01">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -701,7 +701,7 @@
   </summary>
 </histogram>
 
-<histogram name="Cras.StreamEffects" units="value" expires_after="2020-12-01">
+<histogram name="Cras.StreamEffects" units="value" expires_after="2021-12-01">
 <!-- Name completed by histogram_suffixes
      name="Cras.Direction" and
      name="Cras.ClientType" -->
@@ -714,7 +714,7 @@
   </summary>
 </histogram>
 
-<histogram name="Cras.StreamFlags" units="value" expires_after="2021-04-04">
+<histogram name="Cras.StreamFlags" units="value" expires_after="2021-12-01">
 <!-- Name completed by histogram_suffixes
      name="Cras.Direction" and
      name="Cras.ClientType" -->
@@ -728,7 +728,7 @@
 </histogram>
 
 <histogram name="Cras.StreamSamplingFormat" enum="AlsaSampleFormatType"
-    expires_after="2021-01-31">
+    expires_after="2021-12-01">
 <!-- Name completed by histogram_suffixes
      name="Cras.Direction" and
      name="Cras.ClientType" -->
@@ -742,7 +742,7 @@
 </histogram>
 
 <histogram name="Cras.StreamSamplingRate" units="bps"
-    expires_after="2021-01-31">
+    expires_after="2021-12-01">
 <!-- Name completed by histogram_suffixes
      name="Cras.Direction" and
      name="Cras.ClientType" -->
@@ -756,7 +756,7 @@
 </histogram>
 
 <histogram name="Cras.StreamTimeoutMilliSeconds" units="ms"
-    expires_after="2021-04-04">
+    expires_after="2021-12-01">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -768,7 +768,7 @@
 </histogram>
 
 <histogram name="Cras.UnderrunsPerDevice" units="count"
-    expires_after="2021-04-04">
+    expires_after="2021-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index 0e56dfa4..5a95eb1f 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -272,6 +272,7 @@
 crbug.com/948789 [ android-nexus-5x ] startup.mobile/maps_pwa:with_http_cache [ Skip ]
 crbug.com/1030735 [ android-weblayer ] startup.mobile/maps_pwa:with_http_cache [ Skip ]
 crbug.com/1059717 [ android-pixel-2 ] startup.mobile/maps_pwa:with_http_cache [ Skip ]
+crbug.com/1142286 [ android-not-webview ] startup.mobile/cct:coldish:bbc [ Skip ]
 
 # Benchmark: system_health.common_desktop
 crbug.com/903417 [ mac ] system_health.common_desktop/long_running:tools:gmail-foreground [ Skip ]
diff --git a/ui/base/ime/chromeos/ime_assistive_window_handler_interface.h b/ui/base/ime/chromeos/ime_assistive_window_handler_interface.h
index c6195de..0bbbd40 100644
--- a/ui/base/ime/chromeos/ime_assistive_window_handler_interface.h
+++ b/ui/base/ime/chromeos/ime_assistive_window_handler_interface.h
@@ -42,9 +42,6 @@
 
   virtual void ShowSuggestion(const ui::ime::SuggestionDetails& details) {}
 
-  virtual void ShowMultipleSuggestions(
-      const std::vector<base::string16>& suggestions) {}
-
   // Highlights or unhighlights a given assistive button based on the given
   // parameters.
   virtual void SetButtonHighlighted(
diff --git a/ui/file_manager/file_manager/common/images/icon128.png b/ui/file_manager/file_manager/common/images/icon128.png
index aa49a39..a1f75ff1 100644
--- a/ui/file_manager/file_manager/common/images/icon128.png
+++ b/ui/file_manager/file_manager/common/images/icon128.png
Binary files differ
diff --git a/ui/file_manager/file_manager/common/images/icon16.png b/ui/file_manager/file_manager/common/images/icon16.png
index e2017122..c71b1c5 100644
--- a/ui/file_manager/file_manager/common/images/icon16.png
+++ b/ui/file_manager/file_manager/common/images/icon16.png
Binary files differ
diff --git a/ui/file_manager/file_manager/common/images/icon192.png b/ui/file_manager/file_manager/common/images/icon192.png
index c687b69e..a91ea7d7 100644
--- a/ui/file_manager/file_manager/common/images/icon192.png
+++ b/ui/file_manager/file_manager/common/images/icon192.png
Binary files differ
diff --git a/ui/file_manager/file_manager/common/images/icon256.png b/ui/file_manager/file_manager/common/images/icon256.png
index 026a020..8ea6dbe9 100644
--- a/ui/file_manager/file_manager/common/images/icon256.png
+++ b/ui/file_manager/file_manager/common/images/icon256.png
Binary files differ
diff --git a/ui/file_manager/file_manager/common/images/icon32.png b/ui/file_manager/file_manager/common/images/icon32.png
index 93e5019..871427fe 100644
--- a/ui/file_manager/file_manager/common/images/icon32.png
+++ b/ui/file_manager/file_manager/common/images/icon32.png
Binary files differ
diff --git a/ui/file_manager/file_manager/common/images/icon48.png b/ui/file_manager/file_manager/common/images/icon48.png
index ddaaaa50..12ecaf85 100644
--- a/ui/file_manager/file_manager/common/images/icon48.png
+++ b/ui/file_manager/file_manager/common/images/icon48.png
Binary files differ
diff --git a/ui/file_manager/file_manager/common/images/icon64.png b/ui/file_manager/file_manager/common/images/icon64.png
index 0e80be2..22783cfc1 100644
--- a/ui/file_manager/file_manager/common/images/icon64.png
+++ b/ui/file_manager/file_manager/common/images/icon64.png
Binary files differ
diff --git a/ui/file_manager/file_manager/common/images/icon96.png b/ui/file_manager/file_manager/common/images/icon96.png
index 92440de..070057de 100644
--- a/ui/file_manager/file_manager/common/images/icon96.png
+++ b/ui/file_manager/file_manager/common/images/icon96.png
Binary files differ
diff --git a/ui/file_manager/file_manager/common/js/util.js b/ui/file_manager/file_manager/common/js/util.js
index ebea919..9324502 100644
--- a/ui/file_manager/file_manager/common/js/util.js
+++ b/ui/file_manager/file_manager/common/js/util.js
@@ -1238,9 +1238,6 @@
     if (util.isPluginVmEnabled() && entry.fullPath === '/PvmDefault') {
       return true;
     }
-    if (util.isFilesCameraFolderEnabled() && entry.fullPath === '/Camera') {
-      return true;
-    }
   }
 
   if (volumeInfo.volumeType === VolumeManagerCommon.RootType.CROSTINI &&
diff --git a/ui/gfx/buffer_types.h b/ui/gfx/buffer_types.h
index d1102cf5..d15af062 100644
--- a/ui/gfx/buffer_types.h
+++ b/ui/gfx/buffer_types.h
@@ -48,6 +48,7 @@
   SCANOUT_CPU_READ_WRITE,
   SCANOUT_VDA_WRITE,
   GPU_READ_CPU_READ_WRITE,
+  SCANOUT_VEA_CPU_READ,
   SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE,
 
   LAST = SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE
diff --git a/ui/gfx/buffer_usage_util.cc b/ui/gfx/buffer_usage_util.cc
index 7512bfb5..235acbe 100644
--- a/ui/gfx/buffer_usage_util.cc
+++ b/ui/gfx/buffer_usage_util.cc
@@ -22,6 +22,8 @@
       return "SCANOUT_VDA_WRITE";
     case BufferUsage::GPU_READ_CPU_READ_WRITE:
       return "GPU_READ_CPU_READ_WRITE";
+    case BufferUsage::SCANOUT_VEA_CPU_READ:
+      return "SCANOUT_VEA_CPU_READ";
     case BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE:
       return "SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE";
   }
diff --git a/ui/gfx/linux/client_native_pixmap_dmabuf.cc b/ui/gfx/linux/client_native_pixmap_dmabuf.cc
index e570add7..89092eb 100644
--- a/ui/gfx/linux/client_native_pixmap_dmabuf.cc
+++ b/ui/gfx/linux/client_native_pixmap_dmabuf.cc
@@ -191,6 +191,7 @@
     case gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE:
       // R_8 is used as the underlying pixel format for BLOB buffers.
       return format == gfx::BufferFormat::R_8;
+    case gfx::BufferUsage::SCANOUT_VEA_CPU_READ:
     case gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE:
       return format == gfx::BufferFormat::YVU_420 ||
              format == gfx::BufferFormat::YUV_420_BIPLANAR;
diff --git a/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc b/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc
index d8d6e58..f758430 100644
--- a/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc
+++ b/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc
@@ -59,6 +59,7 @@
       case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
       case gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE:
       case gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE:
+      case gfx::BufferUsage::SCANOUT_VEA_CPU_READ:
       case gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE:
         return ClientNativePixmapDmaBuf::ImportFromDmabuf(std::move(handle),
                                                           size, format);
diff --git a/ui/gfx/linux/gbm_util.cc b/ui/gfx/linux/gbm_util.cc
index c516c13..932865f 100644
--- a/ui/gfx/linux/gbm_util.cc
+++ b/ui/gfx/linux/gbm_util.cc
@@ -27,6 +27,9 @@
              GBM_BO_USE_HW_VIDEO_DECODER;
     case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
       return GBM_BO_USE_LINEAR | GBM_BO_USE_TEXTURING;
+    case gfx::BufferUsage::SCANOUT_VEA_CPU_READ:
+      return GBM_BO_USE_LINEAR | GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING |
+             GBM_BO_USE_HW_VIDEO_ENCODER;
     case gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE:
       return GBM_BO_USE_LINEAR | GBM_BO_USE_CAMERA_WRITE | GBM_BO_USE_SCANOUT |
              GBM_BO_USE_TEXTURING | GBM_BO_USE_HW_VIDEO_ENCODER;
diff --git a/ui/gfx/mojom/buffer_types.mojom b/ui/gfx/mojom/buffer_types.mojom
index 95ad129..ab6ea51 100644
--- a/ui/gfx/mojom/buffer_types.mojom
+++ b/ui/gfx/mojom/buffer_types.mojom
@@ -34,6 +34,7 @@
   SCANOUT_CPU_READ_WRITE,
   SCANOUT_VDA_WRITE,
   GPU_READ_CPU_READ_WRITE,
+  SCANOUT_VEA_CPU_READ,
   SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE,
 };
 
diff --git a/ui/gfx/mojom/buffer_types_mojom_traits.h b/ui/gfx/mojom/buffer_types_mojom_traits.h
index 6d309d03..8026d67 100644
--- a/ui/gfx/mojom/buffer_types_mojom_traits.h
+++ b/ui/gfx/mojom/buffer_types_mojom_traits.h
@@ -131,6 +131,8 @@
         return gfx::mojom::BufferUsage::SCANOUT_VDA_WRITE;
       case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
         return gfx::mojom::BufferUsage::GPU_READ_CPU_READ_WRITE;
+      case gfx::BufferUsage::SCANOUT_VEA_CPU_READ:
+        return gfx::mojom::BufferUsage::SCANOUT_VEA_CPU_READ;
       case gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE:
         return gfx::mojom::BufferUsage::
             SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE;
@@ -162,6 +164,9 @@
       case gfx::mojom::BufferUsage::GPU_READ_CPU_READ_WRITE:
         *out = gfx::BufferUsage::GPU_READ_CPU_READ_WRITE;
         return true;
+      case gfx::mojom::BufferUsage::SCANOUT_VEA_CPU_READ:
+        *out = gfx::BufferUsage::SCANOUT_VEA_CPU_READ;
+        return true;
       case gfx::mojom::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE:
         *out = gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE;
         return true;
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index c16009a..80914b9 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -1028,7 +1028,7 @@
     deps += [ "//ui/base/x" ]
   }
 
-  if (use_ozone && is_linux) {
+  if (use_ozone && is_linux && enable_desktop_aura) {
     sources += [
       "test/test_desktop_screen_ozone.cc",
       "test/test_desktop_screen_ozone.h",
diff --git a/ui/webui/resources/js/cr.gni b/ui/webui/resources/js/cr.gni
index 65808835..360d4c4d 100644
--- a/ui/webui/resources/js/cr.gni
+++ b/ui/webui/resources/js/cr.gni
@@ -34,6 +34,7 @@
   "cr.ui.positionPopupAtPoint|positionPopupAtPoint",
   "cr.ui.swallowDoubleClick|swallowDoubleClick",
   "cr.ui.Size|Size",
+  "cr.ui.Splitter|Splitter",
   "cr.ui.StoreObserver|StoreObserver",
   "cr.ui.Tab|Tab",
   "cr.ui.Tree|Tree",