diff --git a/DEPS b/DEPS
index 8d39462..40f408f 100644
--- a/DEPS
+++ b/DEPS
@@ -195,11 +195,11 @@
   # 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': '4efaf5e9feada3eddf286fb362f60d3b11a24e34',
+  'skia_revision': '387fd62a1280a819b531108f12cd00db2b28517f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '7bb48090258056285eefddebf26d55a22121fe5a',
+  'v8_revision': 'ba88e59badac97e4cfa840200aabbe8ceabcbf2e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -207,7 +207,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': '336202d7d6014fd61f430d4ac92d756b33d32ae3',
+  'angle_revision': '4c6903a455dfa3b2f3f822b1757f2e268b91b477',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -215,7 +215,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': 'aa7048b18b2f4713ac2d2158e48c14601a58025c',
+  'pdfium_revision': '538433c720648f67cf6eb2f3ba108ffd97df9eb3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -258,7 +258,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'cd2eebd327e35c839149f7a4d888b046d628df12',
+  'catapult_revision': 'b9b0de8c80ca05f1bcd0472556727cb09f68f38b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -266,7 +266,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': '182a24a6540bde3aaa252af3d531746b47d8bcd6',
+  'devtools_frontend_revision': 'f6bb6691b9336f211da7b8abad8c82661a742a43',
   # 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.
@@ -318,11 +318,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'a7b0fdc90fead0d47e3b83169b38fdd1ea22a539',
+  'dawn_revision': 'd1bca09f4ab36bdc8d413bf2642460b0721267f5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': '60e12c40278b99251d2fa07a0d61a462bf811bd4',
+  'quiche_revision': '5a4f761238065c30c92e90e2f0be13edf54f564f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -342,11 +342,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libavif
   # and whatever else without interference from each other.
-  'libavif_revision': '1d32f88ab33e04b74f4e978bf30f0184d3a96011',
+  'libavif_revision': '0265cd7a10d1425cf42908458a0807e919195914',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling nearby
   # and whatever else without interference from each other.
-  'nearby_revision': '8482024f9c944ff0ef778f74308876dbfa00d4ac',
+  'nearby_revision': 'e9dd5d32f0f7a81b50ba8a5f327edf2ac738f956',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling securemessage
   # and whatever else without interference from each other.
@@ -1486,7 +1486,7 @@
   },
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '3e0a5fc2097e6867909d68d3b0c3e8f89e4864b2',
+    Var('webrtc_git') + '/src.git' + '@' + '1479f79a53045c87073bf550ab6537da269e9370',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1558,7 +1558,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c99c8ab390f734954e7cf9610c86052cc2d54ff1',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@5fa8ec27e9295481c2a1da8165a28a85706e718a',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/DEPS b/android_webview/browser/DEPS
index 17c2c20..730c09b 100644
--- a/android_webview/browser/DEPS
+++ b/android_webview/browser/DEPS
@@ -112,6 +112,7 @@
   "+third_party/blink/public/mojom/speech",
   # Required by AwSettings.
   "+third_party/blink/public/mojom/renderer_preferences.mojom.h",
+  "+third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h",
   # For the content_browser overlay manifest
   "+third_party/blink/public/mojom/input",
 ]
diff --git a/android_webview/browser/aw_settings.cc b/android_webview/browser/aw_settings.cc
index 3480426..d0c5470 100644
--- a/android_webview/browser/aw_settings.cc
+++ b/android_webview/browser/aw_settings.cc
@@ -24,8 +24,8 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "net/http/http_util.h"
-#include "third_party/blink/public/common/web_preferences/web_preferences.h"
 #include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h"
 
 using base::android::ConvertJavaStringToUTF16;
 using base::android::ConvertUTF8ToJavaString;
@@ -438,8 +438,8 @@
 
   web_prefs->autoplay_policy =
       Java_AwSettings_getMediaPlaybackRequiresUserGestureLocked(env, obj)
-          ? blink::web_pref::AutoplayPolicy::kUserGestureRequired
-          : blink::web_pref::AutoplayPolicy::kNoUserGestureRequired;
+          ? blink::mojom::AutoplayPolicy::kUserGestureRequired
+          : blink::mojom::AutoplayPolicy::kNoUserGestureRequired;
 
   ScopedJavaLocalRef<jstring> url =
       Java_AwSettings_getDefaultVideoPosterURLLocked(env, obj);
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index e171c6c..9e0586b3 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1725,7 +1725,6 @@
     "//chromeos/components/quick_answers",
     "//chromeos/components/quick_answers/public/cpp:prefs",
     "//chromeos/ui/base",
-    "//chromeos/ui/frame",
     "//services/viz/public/mojom",
 
     # TODO(https://crbug.com/644336): Make CrasAudioHandler Chrome or Ash only.
@@ -2326,7 +2325,6 @@
     "//chromeos:test_support",
     "//chromeos/strings:strings_grit",
     "//chromeos/ui/base",
-    "//chromeos/ui/frame",
     "//chromeos/ui/vector_icons",
 
     # TODO(https://crbug.com/644336): Make CrasAudioHandler Chrome or Ash only.
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 2930b89..2365b72b 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -2999,6 +2999,17 @@
       <message name="IDS_ASH_SWITCH_TO_LAPTOP_MODE" desc="Alert of switching to laptop mode.">
         Switched to laptop mode
       </message>
+
+      <!-- Multipaste -->
+      <message name="IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE" desc="The label used for the multipaste nudge, to be seen once the user copies and pastes multiple times in a short time span.">
+        Press <ph name="SHORTCUT_KEY_NAME">$1<ex>Launcher</ex></ph> + V to view your clipboard. The last 5 items you've copied are saved to your clipboard.
+      </message>
+      <message name="IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE_LAUNCHER_KEY" desc="The name of the first key to be used for the keyboard shortcut for activating multipaste, when the device has a launcher key.">
+        Launcher
+      </message>
+      <message name="IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE_SEARCH_KEY" desc="The name of the first key to be used for the keyboard shortcut for activating multipaste, when the device has a search key.">
+        Search
+      </message>
     </messages>
   </release>
 </grit>
diff --git a/ash/ash_strings_grd/IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE.png.sha1
new file mode 100644
index 0000000..d942340
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE.png.sha1
@@ -0,0 +1 @@
+d456fd44797415b8ea9c4826046515891e9118e3
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE_LAUNCHER_KEY.png.sha1 b/ash/ash_strings_grd/IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE_LAUNCHER_KEY.png.sha1
new file mode 100644
index 0000000..d942340
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE_LAUNCHER_KEY.png.sha1
@@ -0,0 +1 @@
+d456fd44797415b8ea9c4826046515891e9118e3
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE_SEARCH_KEY.png.sha1 b/ash/ash_strings_grd/IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE_SEARCH_KEY.png.sha1
new file mode 100644
index 0000000..3c3abbc6
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE_SEARCH_KEY.png.sha1
@@ -0,0 +1 @@
+5b624c0c0d59d33775ce9c990a0e91cade5dc868
\ No newline at end of file
diff --git a/ash/assistant/assistant_web_view_delegate_impl.cc b/ash/assistant/assistant_web_view_delegate_impl.cc
index f91255f..b739f5c 100644
--- a/ash/assistant/assistant_web_view_delegate_impl.cc
+++ b/ash/assistant/assistant_web_view_delegate_impl.cc
@@ -5,7 +5,7 @@
 #include "ash/assistant/assistant_web_view_delegate_impl.h"
 
 #include "ash/frame/non_client_frame_view_ash.h"
-#include "chromeos/ui/frame/caption_buttons/caption_button_model.h"
+#include "ash/public/cpp/caption_buttons/caption_button_model.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/caption_button_types.h"
 #include "ui/views/window/non_client_view.h"
@@ -14,8 +14,7 @@
 
 namespace {
 
-class AssistantWebContainerCaptionButtonModel
-    : public chromeos::CaptionButtonModel {
+class AssistantWebContainerCaptionButtonModel : public CaptionButtonModel {
  public:
   AssistantWebContainerCaptionButtonModel() = default;
   ~AssistantWebContainerCaptionButtonModel() override = default;
diff --git a/ash/clipboard/clipboard_nudge.cc b/ash/clipboard/clipboard_nudge.cc
index dbd5ffb..41c23eb 100644
--- a/ash/clipboard/clipboard_nudge.cc
+++ b/ash/clipboard/clipboard_nudge.cc
@@ -9,13 +9,16 @@
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shell.h"
+#include "ash/strings/grit/ash_strings.h"
 #include "ash/style/ash_color_provider.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/chromeos/events/keyboard_layout_util.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/border.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
+#include "ui/views/controls/styled_label.h"
 #include "ui/wm/core/coordinate_conversion.h"
 
 namespace ash {
@@ -32,7 +35,7 @@
 constexpr int kClipboardIconSize = 20;
 
 // The size of the keyboard shortcut icon.
-constexpr int kKeyboardShortcutIconSize = 16;
+constexpr int kKeyboardShortcutIconSize = 14;
 
 // The minimum width of the label.
 constexpr int kMinLabelWidth = 200;
@@ -46,6 +49,13 @@
 // The padding which separates the nudge's border with its inner contents.
 constexpr int kNudgePadding = 16;
 
+bool IsAssistantAvailable() {
+  AssistantStateBase* state = AssistantState::Get();
+  return state->allowed_state() ==
+             chromeos::assistant::AssistantAllowedState::ALLOWED &&
+         state->settings_enabled().value_or(false);
+}
+
 }  // namespace
 
 class ClipboardNudge::ClipboardNudgeView : public views::View {
@@ -69,25 +79,67 @@
     clipboard_icon_->SetImage(
         gfx::CreateVectorIcon(kClipboardIcon, icon_color));
 
-    label_ = AddChildView(std::make_unique<views::Label>());
+    label_ = AddChildView(std::make_unique<views::StyledLabel>());
     label_->SetPaintToLayer();
     label_->layer()->SetFillsBoundsOpaquely(false);
-    label_->SetMultiLine(true);
     label_->SetPosition(gfx::Point(
         kNudgePadding + kClipboardIconSize + kIconLabelSpacing, kNudgePadding));
-    label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    label_->SetVerticalAlignment(gfx::ALIGN_TOP);
-    label_->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor(
-        AshColorProvider::ContentLayerType::kTextColorPrimary));
-    label_->SetBackgroundColor(SK_ColorTRANSPARENT);
 
-    // TODO(mmourgos): Create and set text for |label_|.
-    label_->SetSize(gfx::Size(kMinLabelWidth, kKeyboardShortcutIconSize));
+    bool use_launcher_key = ui::DeviceUsesKeyboardLayout2();
+
+    // Set the keyboard shortcut icon depending on whether search button or
+    // launcher button is being used.
+    gfx::ImageSkia shortcut_icon;
+    if (use_launcher_key) {
+      if (IsAssistantAvailable()) {
+        shortcut_icon = gfx::CreateVectorIcon(gfx::IconDescription(
+            kClipboardLauncherOuterIcon, kKeyboardShortcutIconSize, icon_color,
+            &kClipboardLauncherInnerIcon));
+      } else {
+        shortcut_icon =
+            gfx::CreateVectorIcon(kClipboardLauncherNoAssistantIcon,
+                                  kKeyboardShortcutIconSize, icon_color);
+      }
+    } else {
+      shortcut_icon = gfx::CreateVectorIcon(
+          kClipboardSearchIcon, kKeyboardShortcutIconSize, icon_color);
+    }
+    std::unique_ptr<views::ImageView> keyboard_shortcut_icon;
+    keyboard_shortcut_icon = std::make_unique<views::ImageView>();
+    keyboard_shortcut_icon->SetImage(shortcut_icon);
+    keyboard_shortcut_icon->SetBorder(views::CreateEmptyBorder(2, 4, 0, -2));
+
+    // Set the text for |label_|.
+    base::string16 shortcut_key = l10n_util::GetStringUTF16(
+        use_launcher_key ? IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE_LAUNCHER_KEY
+                         : IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE_SEARCH_KEY);
+    size_t offset;
+    base::string16 label_text = l10n_util::GetStringFUTF16(
+        IDS_ASH_MULTIPASTE_CONTEXTUAL_NUDGE, shortcut_key, &offset);
+    offset = offset + shortcut_key.length();
+    label_->SetText(label_text);
+
+    // Set the color of the text surrounding the shortcut icon.
+    views::StyledLabel::RangeStyleInfo text_color;
+    text_color.override_color = AshColorProvider::Get()->GetContentLayerColor(
+        AshColorProvider::ContentLayerType::kTextColorPrimary);
+    label_->AddStyleRange(gfx::Range(0, offset), text_color);
+    label_->AddStyleRange(gfx::Range(offset + 1, label_text.length()),
+                          text_color);
+
+    // Add the shortcut icon to |label_|.
+    views::StyledLabel::RangeStyleInfo icon_style;
+    icon_style.custom_view = keyboard_shortcut_icon.get();
+    label_->AddCustomView(std::move(keyboard_shortcut_icon));
+    label_->AddStyleRange(gfx::Range(offset, offset + 1), icon_style);
+
+    label_->SizeToFit(kMinLabelWidth);
+    label_->SetDisplayedOnBackgroundColor(SK_ColorTRANSPARENT);
   }
 
   ~ClipboardNudgeView() override = default;
 
-  views::Label* label_ = nullptr;
+  views::StyledLabel* label_ = nullptr;
   views::ImageView* clipboard_icon_ = nullptr;
 };
 
diff --git a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
index 2b4b70f0..6260158 100644
--- a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
+++ b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
@@ -18,8 +18,6 @@
 
 namespace ash {
 
-using ::chromeos::FrameCaptionButtonContainerView;
-
 class FrameCaptionButtonContainerViewTest : public AshTestBase {
  public:
   enum MaximizeAllowed { MAXIMIZE_ALLOWED, MAXIMIZE_DISALLOWED };
@@ -214,7 +212,7 @@
 // Test that the close button is not visible when
 // |ShouldShowCloseButton()| returns false.
 TEST_F(FrameCaptionButtonContainerViewTest, ShouldShowCloseButtonFalse) {
-  chromeos::FrameCaptionButtonContainerView container(CreateTestWidget(
+  FrameCaptionButtonContainerView container(CreateTestWidget(
       MAXIMIZE_ALLOWED, MINIMIZE_ALLOWED, CLOSE_BUTTON_NOT_VISIBLE));
   InitContainer(&container);
   container.Layout();
diff --git a/ash/frame/caption_buttons/frame_size_button_unittest.cc b/ash/frame/caption_buttons/frame_size_button_unittest.cc
index b787a53..6f943f4a 100644
--- a/ash/frame/caption_buttons/frame_size_button_unittest.cc
+++ b/ash/frame/caption_buttons/frame_size_button_unittest.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/ui/frame/caption_buttons/frame_size_button.h"
+#include "ash/public/cpp/caption_buttons/frame_size_button.h"
 
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/window_state.h"
 #include "base/i18n/rtl.h"
 #include "base/run_loop.h"
 #include "chromeos/ui/base/window_properties.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "chromeos/ui/vector_icons/vector_icons.h"
 #include "ui/aura/window.h"
 #include "ui/display/display.h"
@@ -27,8 +27,6 @@
 
 namespace {
 
-using ::chromeos::FrameCaptionButtonContainerView;
-using ::chromeos::FrameSizeButton;
 using ::chromeos::WindowStateType;
 
 class TestWidgetDelegate : public views::WidgetDelegateView {
diff --git a/ash/frame/default_frame_header_unittest.cc b/ash/frame/default_frame_header_unittest.cc
index 83b8dc2..f41b4fb5 100644
--- a/ash/frame/default_frame_header_unittest.cc
+++ b/ash/frame/default_frame_header_unittest.cc
@@ -7,6 +7,8 @@
 #include <memory>
 
 #include "ash/frame/non_client_frame_view_ash.h"
+#include "ash/public/cpp/caption_buttons/frame_back_button.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/public/cpp/window_properties.h"
 #include "ash/test/ash_test_base.h"
@@ -14,8 +16,6 @@
 #include "base/i18n/rtl.h"
 #include "base/stl_util.h"
 #include "base/test/icu_test_util.h"
-#include "chromeos/ui/frame/caption_buttons/frame_back_button.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ui/aura/window.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/gfx/animation/animation_test_api.h"
@@ -25,8 +25,6 @@
 #include "ui/views/window/non_client_view.h"
 #include "ui/wm/core/window_util.h"
 
-using chromeos::FrameBackButton;
-using chromeos::FrameCaptionButtonContainerView;
 using views::NonClientFrameView;
 using views::Widget;
 
diff --git a/ash/frame/header_view.cc b/ash/frame/header_view.cc
index f265c9fe..9a62b54b 100644
--- a/ash/frame/header_view.cc
+++ b/ash/frame/header_view.cc
@@ -6,15 +6,15 @@
 
 #include <memory>
 
+#include "ash/public/cpp/caption_buttons/caption_button_model.h"
+#include "ash/public/cpp/caption_buttons/frame_back_button.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/public/cpp/default_frame_header.h"
 #include "ash/public/cpp/window_properties.h"
 #include "ash/shell.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_state.h"
 #include "base/auto_reset.h"
-#include "chromeos/ui/frame/caption_buttons/caption_button_model.h"
-#include "chromeos/ui/frame/caption_buttons/frame_back_button.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/views/controls/image_view.h"
@@ -57,9 +57,8 @@
   header_content_view_ =
       AddChildView(std::make_unique<HeaderContentView>(this));
 
-  caption_button_container_ =
-      AddChildView(std::make_unique<chromeos::FrameCaptionButtonContainerView>(
-          target_widget_));
+  caption_button_container_ = AddChildView(
+      std::make_unique<FrameCaptionButtonContainerView>(target_widget_));
   caption_button_container_->UpdateCaptionButtonState(false /*=animate*/);
 
   aura::Window* window = target_widget->GetNativeWindow();
@@ -305,7 +304,7 @@
   views::FrameCaptionButton* back_button = frame_header_->GetBackButton();
   if (has_back_button) {
     if (!back_button) {
-      back_button = new chromeos::FrameBackButton();
+      back_button = new FrameBackButton();
       AddChildView(back_button);
       frame_header_->SetBackButton(back_button);
     }
diff --git a/ash/frame/header_view.h b/ash/frame/header_view.h
index b15321f..35707b55 100644
--- a/ash/frame/header_view.h
+++ b/ash/frame/header_view.h
@@ -20,10 +20,6 @@
 #include "ui/base/ui_base_types.h"
 #include "ui/views/view.h"
 
-namespace chromeos {
-class FrameCaptionButtonContainerView;
-}
-
 namespace gfx {
 class ImageSkia;
 }
@@ -38,6 +34,7 @@
 namespace ash {
 
 class DefaultFrameHeader;
+class FrameCaptionButtonContainerView;
 enum class FrameBackButtonState;
 
 // View which paints the frame header (title, caption buttons...). It slides off
@@ -101,7 +98,7 @@
                                intptr_t old) override;
   void OnWindowDestroying(aura::Window* window) override;
 
-  chromeos::FrameCaptionButtonContainerView* caption_button_container() {
+  FrameCaptionButtonContainerView* caption_button_container() {
     return caption_button_container_;
   }
 
@@ -154,8 +151,7 @@
   HeaderContentView* header_content_view_ = nullptr;
 
   // View which contains the window caption buttons.
-  chromeos::FrameCaptionButtonContainerView* caption_button_container_ =
-      nullptr;
+  FrameCaptionButtonContainerView* caption_button_container_ = nullptr;
 
   // The fraction of the header's height which is visible while in fullscreen.
   // This value is meaningless when not in fullscreen.
diff --git a/ash/frame/non_client_frame_view_ash.cc b/ash/frame/non_client_frame_view_ash.cc
index 553fc8f..3485a40 100644
--- a/ash/frame/non_client_frame_view_ash.cc
+++ b/ash/frame/non_client_frame_view_ash.cc
@@ -10,6 +10,7 @@
 
 #include "ash/frame/header_view.h"
 #include "ash/public/cpp/ash_constants.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/public/cpp/default_frame_header.h"
 #include "ash/public/cpp/frame_utils.h"
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h"
@@ -23,7 +24,6 @@
 #include "ash/wm/window_state_observer.h"
 #include "ash/wm/window_util.h"
 #include "base/bind.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
@@ -257,7 +257,7 @@
 }
 
 void NonClientFrameViewAsh::SetCaptionButtonModel(
-    std::unique_ptr<chromeos::CaptionButtonModel> model) {
+    std::unique_ptr<CaptionButtonModel> model) {
   header_view_->caption_button_container()->SetModel(std::move(model));
   header_view_->UpdateCaptionButtons();
 }
@@ -406,7 +406,7 @@
   return false;
 }
 
-chromeos::FrameCaptionButtonContainerView*
+FrameCaptionButtonContainerView*
 NonClientFrameViewAsh::GetFrameCaptionButtonContainerViewForTest() {
   return header_view_->caption_button_container();
 }
diff --git a/ash/frame/non_client_frame_view_ash.h b/ash/frame/non_client_frame_view_ash.h
index 4f549f5..16dab591 100644
--- a/ash/frame/non_client_frame_view_ash.h
+++ b/ash/frame/non_client_frame_view_ash.h
@@ -17,16 +17,13 @@
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/non_client_view.h"
 
-namespace chromeos {
-class FrameCaptionButtonContainerView;
-}
-
 namespace views {
 class Widget;
 }
 
 namespace ash {
 
+class FrameCaptionButtonContainerView;
 class ImmersiveFullscreenController;
 class NonClientFrameViewAshImmersiveHelper;
 
@@ -51,8 +48,7 @@
   static NonClientFrameViewAsh* Get(aura::Window* window);
 
   // Sets the caption button modeland updates the caption buttons.
-  void SetCaptionButtonModel(
-      std::unique_ptr<chromeos::CaptionButtonModel> model);
+  void SetCaptionButtonModel(std::unique_ptr<CaptionButtonModel> model);
 
   // Inits |immersive_fullscreen_controller| so that the controller reveals
   // and hides |header_view_| in immersive fullscreen.
@@ -122,8 +118,7 @@
 
   // Returns the container for the minimize/maximize/close buttons that is
   // held by the HeaderView. Used in testing.
-  chromeos::FrameCaptionButtonContainerView*
-  GetFrameCaptionButtonContainerViewForTest();
+  FrameCaptionButtonContainerView* GetFrameCaptionButtonContainerViewForTest();
 
   // Called when |frame_|'s "paint as active" state has changed.
   void PaintAsActiveChanged();
diff --git a/ash/frame/non_client_frame_view_ash_unittest.cc b/ash/frame/non_client_frame_view_ash_unittest.cc
index d529f590..c1563381 100644
--- a/ash/frame/non_client_frame_view_ash_unittest.cc
+++ b/ash/frame/non_client_frame_view_ash_unittest.cc
@@ -10,6 +10,7 @@
 #include "ash/frame/header_view.h"
 #include "ash/frame/wide_frame_view.h"
 #include "ash/public/cpp/ash_switches.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/public/cpp/default_frame_header.h"
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h"
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h"
@@ -26,7 +27,6 @@
 #include "ash/wm/wm_event.h"
 #include "base/command_line.h"
 #include "base/containers/flat_set.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "chromeos/ui/vector_icons/vector_icons.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
@@ -49,8 +49,6 @@
 
 namespace ash {
 
-using ::chromeos::FrameCaptionButtonContainerView;
-
 // A views::WidgetDelegate which uses a NonClientFrameViewAsh.
 class NonClientFrameViewAshTestWidgetDelegate
     : public views::WidgetDelegateView {
@@ -419,7 +417,7 @@
 
 namespace {
 
-class TestButtonModel : public chromeos::CaptionButtonModel {
+class TestButtonModel : public CaptionButtonModel {
  public:
   TestButtonModel() = default;
   ~TestButtonModel() override = default;
diff --git a/ash/frame/snap_controller_impl.cc b/ash/frame/snap_controller_impl.cc
index 28f24c14..ec4b9b1 100644
--- a/ash/frame/snap_controller_impl.cc
+++ b/ash/frame/snap_controller_impl.cc
@@ -21,8 +21,8 @@
 }
 
 void SnapControllerImpl::ShowSnapPreview(aura::Window* window,
-                                         chromeos::SnapDirection snap) {
-  if (snap == chromeos::SnapDirection::kNone) {
+                                         SnapDirection snap) {
+  if (snap == SnapDirection::kNone) {
     phantom_window_controller_.reset();
     return;
   }
@@ -33,23 +33,21 @@
         std::make_unique<PhantomWindowController>(window);
   }
   gfx::Rect phantom_bounds_in_screen =
-      (snap == chromeos::SnapDirection::kLeft)
+      (snap == SnapDirection::kLeft)
           ? GetDefaultLeftSnappedWindowBoundsInParent(window)
           : GetDefaultRightSnappedWindowBoundsInParent(window);
   ::wm::ConvertRectToScreen(window->parent(), &phantom_bounds_in_screen);
   phantom_window_controller_->Show(phantom_bounds_in_screen);
 }
 
-void SnapControllerImpl::CommitSnap(aura::Window* window,
-                                    chromeos::SnapDirection snap) {
+void SnapControllerImpl::CommitSnap(aura::Window* window, SnapDirection snap) {
   phantom_window_controller_.reset();
-  if (snap == chromeos::SnapDirection::kNone)
+  if (snap == SnapDirection::kNone)
     return;
 
   WindowState* window_state = WindowState::Get(window);
-  const WMEvent snap_event(snap == chromeos::SnapDirection::kLeft
-                               ? WM_EVENT_SNAP_LEFT
-                               : WM_EVENT_SNAP_RIGHT);
+  const WMEvent snap_event(snap == SnapDirection::kLeft ? WM_EVENT_SNAP_LEFT
+                                                        : WM_EVENT_SNAP_RIGHT);
   window_state->OnWMEvent(&snap_event);
 }
 
diff --git a/ash/frame/snap_controller_impl.h b/ash/frame/snap_controller_impl.h
index 61065979..68bf9bc 100644
--- a/ash/frame/snap_controller_impl.h
+++ b/ash/frame/snap_controller_impl.h
@@ -8,23 +8,22 @@
 #include <memory>
 
 #include "ash/ash_export.h"
+#include "ash/public/cpp/caption_buttons/snap_controller.h"
 #include "base/macros.h"
-#include "chromeos/ui/frame/caption_buttons/snap_controller.h"
 
 namespace ash {
 
 class PhantomWindowController;
 
 // A controller for toplevel window actions which can only run in Ash.
-class ASH_EXPORT SnapControllerImpl : public chromeos::SnapController {
+class ASH_EXPORT SnapControllerImpl : public SnapController {
  public:
   SnapControllerImpl();
   ~SnapControllerImpl() override;
 
   bool CanSnap(aura::Window* window) override;
-  void ShowSnapPreview(aura::Window* window,
-                       chromeos::SnapDirection snap) override;
-  void CommitSnap(aura::Window* window, chromeos::SnapDirection snap) override;
+  void ShowSnapPreview(aura::Window* window, SnapDirection snap) override;
+  void CommitSnap(aura::Window* window, SnapDirection snap) override;
 
  private:
   std::unique_ptr<PhantomWindowController> phantom_window_controller_;
diff --git a/ash/frame/wide_frame_view.cc b/ash/frame/wide_frame_view.cc
index 9399c90..611500c 100644
--- a/ash/frame/wide_frame_view.cc
+++ b/ash/frame/wide_frame_view.cc
@@ -6,6 +6,7 @@
 
 #include "ash/frame/header_view.h"
 #include "ash/frame/non_client_frame_view_ash.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/public/cpp/default_frame_header.h"
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h"
 #include "ash/public/cpp/window_properties.h"
@@ -14,7 +15,6 @@
 #include "ash/wm/window_state.h"
 #include "ash/wm/wm_event.h"
 #include "base/metrics/user_metrics.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_targeter.h"
 #include "ui/display/display.h"
@@ -78,7 +78,7 @@
 }
 
 void WideFrameView::SetCaptionButtonModel(
-    std::unique_ptr<chromeos::CaptionButtonModel> model) {
+    std::unique_ptr<CaptionButtonModel> model) {
   header_view_->caption_button_container()->SetModel(std::move(model));
   header_view_->UpdateCaptionButtons();
 }
diff --git a/ash/frame/wide_frame_view.h b/ash/frame/wide_frame_view.h
index a843bbc6..32b684da 100644
--- a/ash/frame/wide_frame_view.h
+++ b/ash/frame/wide_frame_view.h
@@ -6,9 +6,9 @@
 #define ASH_FRAME_WIDE_FRAME_VIEW_H_
 
 #include "ash/ash_export.h"
+#include "ash/public/cpp/caption_buttons/caption_button_model.h"
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller_delegate.h"
 #include "ash/wm/overview/overview_observer.h"
-#include "chromeos/ui/frame/caption_buttons/caption_button_model.h"
 #include "ui/aura/window_observer.h"
 #include "ui/display/display_observer.h"
 #include "ui/views/widget/widget_delegate.h"
@@ -44,8 +44,7 @@
   void Init(ImmersiveFullscreenController* controller);
 
   // Set the caption model for caption buttions on this frame.
-  void SetCaptionButtonModel(
-      std::unique_ptr<chromeos::CaptionButtonModel> mode);
+  void SetCaptionButtonModel(std::unique_ptr<CaptionButtonModel> mode);
 
   HeaderView* header_view() { return header_view_; }
 
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index fdf9769..8f82490 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -104,6 +104,16 @@
     "assistant/conversation_starters_client.h",
     "back_gesture_contextual_nudge_controller.h",
     "back_gesture_contextual_nudge_delegate.h",
+    "caption_buttons/caption_button_model.h",
+    "caption_buttons/frame_back_button.cc",
+    "caption_buttons/frame_back_button.h",
+    "caption_buttons/frame_caption_button_container_view.cc",
+    "caption_buttons/frame_caption_button_container_view.h",
+    "caption_buttons/frame_size_button.cc",
+    "caption_buttons/frame_size_button.h",
+    "caption_buttons/frame_size_button_delegate.h",
+    "caption_buttons/snap_controller.cc",
+    "caption_buttons/snap_controller.h",
     "cast_config_controller.cc",
     "cast_config_controller.h",
     "child_accounts/parent_access_controller.cc",
@@ -331,7 +341,6 @@
     "//chromeos/services/cellular_setup:in_process_esim_manager",
     "//chromeos/services/network_config:in_process_instance",
     "//chromeos/ui/base",
-    "//chromeos/ui/frame",
     "//chromeos/ui/vector_icons",
     "//components/pref_registry",
     "//components/prefs",
diff --git a/chromeos/ui/frame/caption_buttons/caption_button_model.h b/ash/public/cpp/caption_buttons/caption_button_model.h
similarity index 75%
rename from chromeos/ui/frame/caption_buttons/caption_button_model.h
rename to ash/public/cpp/caption_buttons/caption_button_model.h
index 8593203..33ff4d5 100644
--- a/chromeos/ui/frame/caption_buttons/caption_button_model.h
+++ b/ash/public/cpp/caption_buttons/caption_button_model.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_UI_FRAME_CAPTION_BUTTONS_CAPTION_BUTTON_MODEL_H_
-#define CHROMEOS_UI_FRAME_CAPTION_BUTTONS_CAPTION_BUTTON_MODEL_H_
+#ifndef ASH_PUBLIC_CPP_CAPTION_BUTTONS_CAPTION_BUTTON_MODEL_H_
+#define ASH_PUBLIC_CPP_CAPTION_BUTTONS_CAPTION_BUTTON_MODEL_H_
 
 #include "ui/views/window/caption_button_types.h"
 
-namespace chromeos {
+namespace ash {
 
 // CaptionButtonModel describes the state of caption buttons
 // for each CaptionButtonIcon types.
@@ -26,6 +26,6 @@
   virtual bool InZoomMode() const = 0;
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
-#endif  // CHROMEOS_UI_FRAME_CAPTION_BUTTONS_CAPTION_BUTTON_MODEL_H_
+#endif  // ASH_PUBLIC_CPP_CAPTION_BUTTONS_CAPTION_BUTTON_MODEL_H_
diff --git a/chromeos/ui/frame/caption_buttons/frame_back_button.cc b/ash/public/cpp/caption_buttons/frame_back_button.cc
similarity index 93%
rename from chromeos/ui/frame/caption_buttons/frame_back_button.cc
rename to ash/public/cpp/caption_buttons/frame_back_button.cc
index f2b9041..cb2a5ae 100644
--- a/chromeos/ui/frame/caption_buttons/frame_back_button.cc
+++ b/ash/public/cpp/caption_buttons/frame_back_button.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/ui/frame/caption_buttons/frame_back_button.h"
+#include "ash/public/cpp/caption_buttons/frame_back_button.h"
 
 #include "chromeos/ui/vector_icons/vector_icons.h"
 #include "ui/aura/window.h"
@@ -15,7 +15,7 @@
 #include "ui/views/window/caption_button_layout_constants.h"
 #include "ui/views/window/frame_caption_button.h"
 
-namespace chromeos {
+namespace ash {
 
 FrameBackButton::FrameBackButton()
     : FrameCaptionButton(this, views::CAPTION_BUTTON_ICON_BACK, HTMENU) {
@@ -38,4 +38,4 @@
   ignore_result(root_window->GetHost()->SendEventToSink(&release_key_event));
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/ash/public/cpp/caption_buttons/frame_back_button.h b/ash/public/cpp/caption_buttons/frame_back_button.h
new file mode 100644
index 0000000..32182eb8a
--- /dev/null
+++ b/ash/public/cpp/caption_buttons/frame_back_button.h
@@ -0,0 +1,30 @@
+// Copyright 2017 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 ASH_PUBLIC_CPP_CAPTION_BUTTONS_FRAME_BACK_BUTTON_H_
+#define ASH_PUBLIC_CPP_CAPTION_BUTTONS_FRAME_BACK_BUTTON_H_
+
+#include "ash/public/cpp/ash_public_export.h"
+#include "ui/views/window/frame_caption_button.h"
+
+namespace ash {
+
+// A button to send back key events. It's used in Chrome hosted app windows,
+// among other places.
+class ASH_PUBLIC_EXPORT FrameBackButton : public views::FrameCaptionButton,
+                                          public views::ButtonListener {
+ public:
+  FrameBackButton();
+  ~FrameBackButton() override;
+
+  // views::ButtonListener:
+  void ButtonPressed(Button* sender, const ui::Event& event) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FrameBackButton);
+};
+
+}  // namespace ash
+
+#endif  //  ASH_PUBLIC_CPP_CAPTION_BUTTONS_FRAME_BACK_BUTTON_H_
diff --git a/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc b/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc
similarity index 97%
rename from chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc
rename to ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc
index 59db93c..a28cfc7 100644
--- a/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc
+++ b/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 
 #include <cmath>
 #include <map>
 
+#include "ash/public/cpp/caption_buttons/caption_button_model.h"
+#include "ash/public/cpp/caption_buttons/frame_size_button.h"
+#include "ash/public/cpp/caption_buttons/snap_controller.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/numerics/ranges.h"
 #include "chromeos/ui/base/tablet_state.h"
-#include "chromeos/ui/frame/caption_buttons/caption_button_model.h"
-#include "chromeos/ui/frame/caption_buttons/frame_size_button.h"
-#include "chromeos/ui/frame/caption_buttons/snap_controller.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/hit_test.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -31,7 +31,7 @@
 #include "ui/views/widget/widget_delegate.h"
 #include "ui/views/window/frame_caption_button.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -473,7 +473,7 @@
   views::FrameCaptionButton* buttons[] = {menu_button_, minimize_button_,
                                           size_button_, close_button_};
   int min_squared_distance = INT_MAX;
-  views::FrameCaptionButton* closest_button = nullptr;
+  views::FrameCaptionButton* closest_button = NULL;
   for (size_t i = 0; i < base::size(buttons); ++i) {
     views::FrameCaptionButton* button = buttons[i];
     if (!button->GetVisible())
@@ -520,4 +520,4 @@
   SnapController::Get()->CommitSnap(frame_->GetNativeWindow(), snap);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h b/ash/public/cpp/caption_buttons/frame_caption_button_container_view.h
similarity index 87%
rename from chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h
rename to ash/public/cpp/caption_buttons/frame_caption_button_container_view.h
index bff904e..61cd215 100644
--- a/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h
+++ b/ash/public/cpp/caption_buttons/frame_caption_button_container_view.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_
-#define CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_
+#ifndef ASH_PUBLIC_CPP_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_
+#define ASH_PUBLIC_CPP_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_
 
 #include <map>
 
-#include "base/component_export.h"
+#include "ash/public/cpp/ash_public_export.h"
+#include "ash/public/cpp/caption_buttons/caption_button_model.h"
+#include "ash/public/cpp/caption_buttons/frame_size_button_delegate.h"
+#include "ash/public/cpp/caption_buttons/snap_controller.h"
 #include "base/macros.h"
-#include "chromeos/ui/frame/caption_buttons/caption_button_model.h"
-#include "chromeos/ui/frame/caption_buttons/frame_size_button_delegate.h"
-#include "chromeos/ui/frame/caption_buttons/snap_controller.h"
 #include "ui/views/animation/animation_delegate_views.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/view.h"
@@ -26,15 +26,11 @@
 class Widget;
 }
 
-namespace chromeos {
+namespace ash {
 
 // Container view for the frame caption buttons. It performs the appropriate
 // action when a caption button is clicked.
-//
-// NOTE: The associated test (frame_caption_button_container_view_unittest.cc)
-// is in //ash because it needs ash test support (AshTestBase and its
-// utilities).
-class COMPONENT_EXPORT(CHROMEOS_UI_FRAME) FrameCaptionButtonContainerView
+class ASH_PUBLIC_EXPORT FrameCaptionButtonContainerView
     : public views::View,
       public views::ButtonListener,
       public FrameSizeButtonDelegate,
@@ -47,7 +43,7 @@
   ~FrameCaptionButtonContainerView() override;
 
   // For testing.
-  class COMPONENT_EXPORT(CHROMEOS_UI_FRAME) TestApi {
+  class ASH_PUBLIC_EXPORT TestApi {
    public:
     explicit TestApi(FrameCaptionButtonContainerView* container_view)
         : container_view_(container_view) {}
@@ -170,6 +166,6 @@
   DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerView);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
-#endif  // CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_
+#endif  // ASH_PUBLIC_CPP_CAPTION_BUTTONS_FRAME_CAPTION_BUTTON_CONTAINER_VIEW_H_
diff --git a/chromeos/ui/frame/caption_buttons/frame_size_button.cc b/ash/public/cpp/caption_buttons/frame_size_button.cc
similarity index 97%
rename from chromeos/ui/frame/caption_buttons/frame_size_button.cc
rename to ash/public/cpp/caption_buttons/frame_size_button.cc
index 7a1e1d58..e67f494 100644
--- a/chromeos/ui/frame/caption_buttons/frame_size_button.cc
+++ b/ash/public/cpp/caption_buttons/frame_size_button.cc
@@ -2,21 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/ui/frame/caption_buttons/frame_size_button.h"
+#include "ash/public/cpp/caption_buttons/frame_size_button.h"
 
 #include <memory>
 
+#include "ash/public/cpp/caption_buttons/snap_controller.h"
 #include "base/i18n/rtl.h"
 #include "base/metrics/user_metrics.h"
 #include "chromeos/ui/base/window_properties.h"
-#include "chromeos/ui/frame/caption_buttons/snap_controller.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
 #include "ui/base/hit_test.h"
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/views/widget/widget.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -277,7 +277,7 @@
       HitTestButton(closest_button, event_location_in_screen)) {
     return closest_button;
   }
-  return nullptr;
+  return NULL;
 }
 
 bool FrameSizeButton::CommitSnap(const ui::LocatedEvent& event) {
@@ -313,4 +313,4 @@
   delegate_->SetButtonsToNormal(animate);
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chromeos/ui/frame/caption_buttons/frame_size_button.h b/ash/public/cpp/caption_buttons/frame_size_button.h
similarity index 89%
rename from chromeos/ui/frame/caption_buttons/frame_size_button.h
rename to ash/public/cpp/caption_buttons/frame_size_button.h
index f868d0be..58023fa 100644
--- a/chromeos/ui/frame/caption_buttons/frame_size_button.h
+++ b/ash/public/cpp/caption_buttons/frame_size_button.h
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_H_
-#define CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_H_
+#ifndef ASH_PUBLIC_CPP_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_H_
+#define ASH_PUBLIC_CPP_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_H_
 
 #include <memory>
 
-#include "base/component_export.h"
+#include "ash/public/cpp/ash_public_export.h"
+#include "ash/public/cpp/caption_buttons/frame_size_button_delegate.h"
 #include "base/macros.h"
 #include "base/timer/timer.h"
-#include "chromeos/ui/frame/caption_buttons/frame_size_button_delegate.h"
 #include "ui/views/window/frame_caption_button.h"
 
-namespace chromeos {
+namespace ash {
 
 // The maximize/restore button.
 // When the mouse is pressed over the size button or the size button is touched:
@@ -24,8 +24,7 @@
 // When the drag terminates, the action for the button underneath the mouse
 // is executed. For the sake of simplicity, the size button is the event
 // handler for a click starting on the size button and the entire drag.
-class COMPONENT_EXPORT(CHROMEOS_UI_CAPTION_BUTTONS) FrameSizeButton
-    : public views::FrameCaptionButton {
+class ASH_PUBLIC_EXPORT FrameSizeButton : public views::FrameCaptionButton {
  public:
   FrameSizeButton(views::ButtonListener* listener,
                   FrameSizeButtonDelegate* delegate);
@@ -104,6 +103,6 @@
   DISALLOW_COPY_AND_ASSIGN(FrameSizeButton);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
-#endif  // CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_H_
+#endif  // ASH_PUBLIC_CPP_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_H_
diff --git a/chromeos/ui/frame/caption_buttons/frame_size_button_delegate.h b/ash/public/cpp/caption_buttons/frame_size_button_delegate.h
similarity index 83%
rename from chromeos/ui/frame/caption_buttons/frame_size_button_delegate.h
rename to ash/public/cpp/caption_buttons/frame_size_button_delegate.h
index 8141a775..7c48f16 100644
--- a/chromeos/ui/frame/caption_buttons/frame_size_button_delegate.h
+++ b/ash/public/cpp/caption_buttons/frame_size_button_delegate.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_DELEGATE_H_
-#define CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_DELEGATE_H_
+#ifndef ASH_PUBLIC_CPP_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_DELEGATE_H_
+#define ASH_PUBLIC_CPP_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_DELEGATE_H_
 
-#include "base/component_export.h"
+#include "ash/public/cpp/ash_public_export.h"
 #include "ui/views/window/caption_button_types.h"
 
 namespace gfx {
@@ -16,12 +16,12 @@
 class FrameCaptionButton;
 }
 
-namespace chromeos {
+namespace ash {
 
 enum class SnapDirection;
 
 // Delegate interface for FrameSizeButton.
-class COMPONENT_EXPORT(CHROMEOS_UI_FRAME) FrameSizeButtonDelegate {
+class ASH_PUBLIC_EXPORT FrameSizeButtonDelegate {
  public:
   enum Animate { ANIMATE_YES, ANIMATE_NO };
 
@@ -58,6 +58,6 @@
   virtual ~FrameSizeButtonDelegate() {}
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
-#endif  // CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_DELEGATE_H_
+#endif  // ASH_PUBLIC_CPP_CAPTION_BUTTONS_FRAME_SIZE_BUTTON_DELEGATE_H_
diff --git a/chromeos/ui/frame/caption_buttons/snap_controller.cc b/ash/public/cpp/caption_buttons/snap_controller.cc
similarity index 82%
rename from chromeos/ui/frame/caption_buttons/snap_controller.cc
rename to ash/public/cpp/caption_buttons/snap_controller.cc
index 3c62788..2cf48b9a 100644
--- a/chromeos/ui/frame/caption_buttons/snap_controller.cc
+++ b/ash/public/cpp/caption_buttons/snap_controller.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/ui/frame/caption_buttons/snap_controller.h"
+#include "ash/public/cpp/caption_buttons/snap_controller.h"
 
 #include "base/check_op.h"
 
-namespace chromeos {
+namespace ash {
 
 namespace {
 
@@ -29,4 +29,4 @@
   g_instance = this;
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chromeos/ui/frame/caption_buttons/snap_controller.h b/ash/public/cpp/caption_buttons/snap_controller.h
similarity index 78%
rename from chromeos/ui/frame/caption_buttons/snap_controller.h
rename to ash/public/cpp/caption_buttons/snap_controller.h
index cd98aa54c..be58f9ec 100644
--- a/chromeos/ui/frame/caption_buttons/snap_controller.h
+++ b/ash/public/cpp/caption_buttons/snap_controller.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_UI_FRAME_CAPTION_BUTTONS_SNAP_CONTROLLER_H_
-#define CHROMEOS_UI_FRAME_CAPTION_BUTTONS_SNAP_CONTROLLER_H_
+#ifndef ASH_PUBLIC_CPP_CAPTION_BUTTONS_SNAP_CONTROLLER_H_
+#define ASH_PUBLIC_CPP_CAPTION_BUTTONS_SNAP_CONTROLLER_H_
 
-#include "base/component_export.h"
+#include "ash/public/cpp/ash_public_export.h"
 
 namespace aura {
 class Window;
 }
 
-namespace chromeos {
+namespace ash {
 
 // The previewed snap state for a window, corresponding to the use of a
 // PhantomWindowController.
@@ -23,7 +23,7 @@
 
 // This interface handles snap actions to be performed on a top level window.
 // The singleton that implements the interface is provided by Ash.
-class COMPONENT_EXPORT(CHROMEOS_UI_FRAME) SnapController {
+class ASH_PUBLIC_EXPORT SnapController {
  public:
   virtual ~SnapController();
 
@@ -43,6 +43,6 @@
   SnapController();
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
-#endif  // CHROMEOS_UI_FRAME_CAPTION_BUTTONS_SNAP_CONTROLLER_H_
+#endif  // ASH_PUBLIC_CPP_CAPTION_BUTTONS_SNAP_CONTROLLER_H_
diff --git a/ash/public/cpp/default_frame_header.cc b/ash/public/cpp/default_frame_header.cc
index 9e736b4..b205f83f 100644
--- a/ash/public/cpp/default_frame_header.cc
+++ b/ash/public/cpp/default_frame_header.cc
@@ -5,12 +5,12 @@
 #include "ash/public/cpp/default_frame_header.h"
 
 #include "ash/public/cpp/ash_constants.h"
+#include "ash/public/cpp/caption_buttons/caption_button_model.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/public/cpp/window_properties.h"
 #include "base/logging.h"  // DCHECK
 #include "chromeos/ui/base/window_properties.h"
 #include "chromeos/ui/base/window_state_type.h"
-#include "chromeos/ui/frame/caption_buttons/caption_button_model.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_utils.h"
@@ -64,7 +64,7 @@
 DefaultFrameHeader::DefaultFrameHeader(
     views::Widget* target_widget,
     views::View* header_view,
-    chromeos::FrameCaptionButtonContainerView* caption_button_container)
+    FrameCaptionButtonContainerView* caption_button_container)
     : FrameHeader(target_widget, header_view) {
   DCHECK(caption_button_container);
   SetCaptionButtonContainer(caption_button_container);
diff --git a/ash/public/cpp/default_frame_header.h b/ash/public/cpp/default_frame_header.h
index efa8bf0..8bb5dba 100644
--- a/ash/public/cpp/default_frame_header.h
+++ b/ash/public/cpp/default_frame_header.h
@@ -21,10 +21,9 @@
 class ASH_PUBLIC_EXPORT DefaultFrameHeader : public FrameHeader {
  public:
   // DefaultFrameHeader does not take ownership of any of the parameters.
-  DefaultFrameHeader(
-      views::Widget* target_widget,
-      views::View* header_view,
-      chromeos::FrameCaptionButtonContainerView* caption_button_container);
+  DefaultFrameHeader(views::Widget* target_widget,
+                     views::View* header_view,
+                     FrameCaptionButtonContainerView* caption_button_container);
   ~DefaultFrameHeader() override;
 
   SkColor active_frame_color_for_testing() { return active_frame_color_; }
diff --git a/ash/public/cpp/frame_header.cc b/ash/public/cpp/frame_header.cc
index 042d86c..09a23a16 100644
--- a/ash/public/cpp/frame_header.cc
+++ b/ash/public/cpp/frame_header.cc
@@ -4,11 +4,11 @@
 
 #include "ash/public/cpp/frame_header.h"
 
+#include "ash/public/cpp/caption_buttons/caption_button_model.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/public/cpp/frame_utils.h"
 #include "ash/public/cpp/window_properties.h"
 #include "base/logging.h"  // DCHECK
-#include "chromeos/ui/frame/caption_buttons/caption_button_model.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "chromeos/ui/vector_icons/vector_icons.h"
 #include "ui/base/class_property.h"
 #include "ui/compositor/layer_animation_observer.h"
@@ -261,7 +261,7 @@
   return back_button_;
 }
 
-const chromeos::CaptionButtonModel* FrameHeader::GetCaptionButtonModel() const {
+const CaptionButtonModel* FrameHeader::GetCaptionButtonModel() const {
   return caption_button_container_->model();
 }
 
@@ -317,7 +317,7 @@
 }
 
 void FrameHeader::SetCaptionButtonContainer(
-    chromeos::FrameCaptionButtonContainerView* caption_button_container) {
+    FrameCaptionButtonContainerView* caption_button_container) {
   caption_button_container_ = caption_button_container;
   caption_button_container_->SetButtonImage(views::CAPTION_BUTTON_ICON_MINIMIZE,
                                             views::kWindowControlMinimizeIcon);
@@ -365,7 +365,7 @@
                      : views::kWindowControlMaximizeIcon;
   // TODO(crbug.com/1092005): Investigate if we can move this to
   // CaptionButtonModel and just check the model in
-  // chromeos::FrameCaptionButtonContainerView.
+  // FrameCaptionButtonContainerView.
   const bool use_restore_frame = ash::ShouldUseRestoreFrame(target_widget_);
   caption_button_container()->SetButtonImage(
       views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE,
diff --git a/ash/public/cpp/frame_header.h b/ash/public/cpp/frame_header.h
index 9f1e495..89ce587 100644
--- a/ash/public/cpp/frame_header.h
+++ b/ash/public/cpp/frame_header.h
@@ -6,19 +6,15 @@
 #define ASH_PUBLIC_CPP_FRAME_HEADER_H_
 
 #include "ash/public/cpp/ash_public_export.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "base/callback.h"
 #include "base/optional.h"
 #include "base/strings/string16.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/ui_base_types.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/views/window/frame_caption_button.h"
 
-namespace chromeos {
-class CaptionButtonModel;
-}  // namespace chromeos
-
 namespace gfx {
 class Canvas;
 class Rect;
@@ -31,6 +27,7 @@
 }  // namespace views
 
 namespace ash {
+class CaptionButtonModel;
 
 // Helper class for managing the window header.
 class ASH_PUBLIC_EXPORT FrameHeader {
@@ -76,7 +73,7 @@
   void SetLeftHeaderView(views::View* view);
   void SetBackButton(views::FrameCaptionButton* view);
   views::FrameCaptionButton* GetBackButton() const;
-  const chromeos::CaptionButtonModel* GetCaptionButtonModel() const;
+  const CaptionButtonModel* GetCaptionButtonModel() const;
 
   // Updates the frame header painting to reflect a change in frame colors.
   virtual void UpdateFrameColors() = 0;
@@ -89,7 +86,7 @@
 
   views::View* view() { return view_; }
 
-  chromeos::FrameCaptionButtonContainerView* caption_button_container() {
+  FrameCaptionButtonContainerView* caption_button_container() {
     return caption_button_container_;
   }
 
@@ -109,7 +106,7 @@
   void PaintTitleBar(gfx::Canvas* canvas);
 
   void SetCaptionButtonContainer(
-      chromeos::FrameCaptionButtonContainerView* caption_button_container);
+      FrameCaptionButtonContainerView* caption_button_container);
 
   Mode mode() const { return mode_; }
 
@@ -140,8 +137,7 @@
   views::View* view_;
   views::FrameCaptionButton* back_button_ = nullptr;  // May remain nullptr.
   views::View* left_header_view_ = nullptr;    // May remain nullptr.
-  chromeos::FrameCaptionButtonContainerView* caption_button_container_ =
-      nullptr;
+  FrameCaptionButtonContainerView* caption_button_container_ = nullptr;
   FrameAnimatorView* frame_animator_ = nullptr;  // owned by view tree.
 
   // The height of the header to paint.
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn
index 1bd3ffd..bacec8e5 100644
--- a/ash/resources/vector_icons/BUILD.gn
+++ b/ash/resources/vector_icons/BUILD.gn
@@ -38,6 +38,10 @@
     "check_circle.icon",
     "chevron_right.icon",
     "clipboard.icon",
+    "clipboard_launcher_inner.icon",
+    "clipboard_launcher_no_assistant.icon",
+    "clipboard_launcher_outer.icon",
+    "clipboard_search.icon",
     "close_button.icon",
     "copy.icon",
     "dark_theme_color_mode.icon",
diff --git a/ash/resources/vector_icons/clipboard_launcher_inner.icon b/ash/resources/vector_icons/clipboard_launcher_inner.icon
new file mode 100644
index 0000000..286ddcd
--- /dev/null
+++ b/ash/resources/vector_icons/clipboard_launcher_inner.icon
@@ -0,0 +1,5 @@
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 8, 13,
+ARC_TO, 5, 5, 0, 1, 1, 8, 3,
+R_ARC_TO, 5, 5, 0, 0, 1, 0, 10,
+CLOSE
\ No newline at end of file
diff --git a/ash/resources/vector_icons/clipboard_launcher_no_assistant.icon b/ash/resources/vector_icons/clipboard_launcher_no_assistant.icon
new file mode 100644
index 0000000..95443f1e
--- /dev/null
+++ b/ash/resources/vector_icons/clipboard_launcher_no_assistant.icon
@@ -0,0 +1,9 @@
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 8, 15,
+ARC_TO, 7, 7, 0, 1, 1, 8, 1,
+R_ARC_TO, 7, 7, 0, 0, 1, 0, 14,
+CLOSE,
+R_MOVE_TO, 0, -1.61f,
+R_ARC_TO, 5.39f, 5.39f, 0, 1, 0, 0, -10.77f,
+R_ARC_TO, 5.39f, 5.39f, 0, 0, 0, 0, 10.77f,
+CLOSE
\ No newline at end of file
diff --git a/ash/resources/vector_icons/clipboard_launcher_outer.icon b/ash/resources/vector_icons/clipboard_launcher_outer.icon
new file mode 100644
index 0000000..32ed6435
--- /dev/null
+++ b/ash/resources/vector_icons/clipboard_launcher_outer.icon
@@ -0,0 +1,9 @@
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 8, 16,
+ARC_TO, 8, 8, 0, 1, 1, 8, 0,
+R_ARC_TO, 8, 8, 0, 0, 1, 0, 16,
+CLOSE,
+R_MOVE_TO, 0, -1,
+ARC_TO, 7, 7, 0, 1, 0, 8, 1,
+R_ARC_TO, 7, 7, 0, 0, 0, 0, 14,
+CLOSE
\ No newline at end of file
diff --git a/ash/resources/vector_icons/clipboard_search.icon b/ash/resources/vector_icons/clipboard_search.icon
new file mode 100644
index 0000000..9788f1f
--- /dev/null
+++ b/ash/resources/vector_icons/clipboard_search.icon
@@ -0,0 +1,15 @@
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 15.49f, 14,
+R_LINE_TO, -3.73f, -3.73f,
+CUBIC_TO, 12.53f, 9.2f, 13, 7.91f, 13, 6.5f,
+ARC_TO, 6.5f, 6.5f, 0, 1, 0, 6.5f, 13,
+R_CUBIC_TO, 1.41f, 0, 2.7f, -0.47f, 3.77f, -1.24f,
+LINE_TO, 14, 15.49f,
+LINE_TO, 15.49f, 14,
+CLOSE,
+MOVE_TO, 2, 6.5f,
+CUBIC_TO, 2, 4.01f, 4.01f, 2, 6.5f, 2,
+CUBIC_TO_SHORTHAND, 11, 4.01f, 11, 6.5f,
+CUBIC_TO_SHORTHAND, 8.99f, 11, 6.5f, 11,
+CUBIC_TO_SHORTHAND, 2, 8.99f, 2, 6.5f,
+CLOSE
\ No newline at end of file
diff --git a/ash/search_box/search_box_view_base.cc b/ash/search_box/search_box_view_base.cc
index f5fa6c3..2f945b8 100644
--- a/ash/search_box/search_box_view_base.cc
+++ b/ash/search_box/search_box_view_base.cc
@@ -47,6 +47,10 @@
 
 constexpr SkColor kSearchTextColor = SkColorSetRGB(0x33, 0x33, 0x33);
 
+// Color of placeholder text in zero query state.
+constexpr SkColor kZeroQuerySearchboxColor =
+    SkColorSetARGB(0x8A, 0x00, 0x00, 0x00);
+
 }  // namespace
 
 // A background that paints a solid white rounded rect with a thin grey
@@ -337,10 +341,13 @@
 
   is_search_box_active_ = active;
   UpdateSearchIcon();
+  UpdateBackgroundColor(kSearchBoxBackgroundDefault);
   search_box_->set_placeholder_text_draw_flags(
       active ? (base::i18n::IsRTL() ? gfx::Canvas::TEXT_ALIGN_RIGHT
                                     : gfx::Canvas::TEXT_ALIGN_LEFT)
              : gfx::Canvas::TEXT_ALIGN_CENTER);
+  search_box_->set_placeholder_text_color(active ? kZeroQuerySearchboxColor
+                                                 : search_box_color_);
   search_box_->SetCursorEnabled(active);
 
   if (active) {
diff --git a/ash/shell.h b/ash/shell.h
index f47bc16d..cfee3fe 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -32,10 +32,6 @@
 class Window;
 }  // namespace aura
 
-namespace chromeos {
-class SnapController;
-}  // namespace chromeos
-
 namespace dbus {
 class Bus;
 }
@@ -179,6 +175,7 @@
 class ShellObserver;
 class ShutdownControllerImpl;
 class SmsObserver;
+class SnapController;
 class StickyKeysController;
 class SystemGestureEventFilter;
 class SystemModalContainerEventFilter;
@@ -832,7 +829,7 @@
 
   std::unique_ptr<DockedMagnifierControllerImpl> docked_magnifier_controller_;
 
-  std::unique_ptr<chromeos::SnapController> snap_controller_;
+  std::unique_ptr<SnapController> snap_controller_;
 
   // |native_cursor_manager_| is owned by |cursor_manager_|, but we keep a
   // pointer to vend to test code.
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 0438b0cc..9a13885 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1779,6 +1779,7 @@
         "allocator/partition_allocator/partition_page.h",
         "allocator/partition_allocator/partition_ref_count.cc",
         "allocator/partition_allocator/partition_ref_count.h",
+        "allocator/partition_allocator/partition_root.h",
         "allocator/partition_allocator/partition_tag.h",
         "allocator/partition_allocator/partition_tag_bitmap.h",
         "allocator/partition_allocator/partition_tls.h",
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h
index cb83aef..8742b6b 100644
--- a/base/allocator/partition_allocator/partition_alloc.h
+++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -66,11 +66,11 @@
 #include "base/allocator/partition_allocator/partition_alloc_forward.h"
 #include "base/allocator/partition_allocator/partition_bucket.h"
 #include "base/allocator/partition_allocator/partition_cookie.h"
-#include "base/allocator/partition_allocator/partition_direct_map_extent.h"
 #include "base/allocator/partition_allocator/partition_lock.h"
 #include "base/allocator/partition_allocator/partition_oom.h"
 #include "base/allocator/partition_allocator/partition_page.h"
 #include "base/allocator/partition_allocator/partition_ref_count.h"
+#include "base/allocator/partition_allocator/partition_root.h"
 #include "base/allocator/partition_allocator/partition_tag.h"
 #include "base/allocator/partition_allocator/pcscan.h"
 #include "base/allocator/partition_allocator/thread_cache.h"
@@ -371,239 +371,12 @@
 
 }  // namespace
 
-// Options struct used to configure PartitionRoot and PartitionAllocator.
-struct PartitionOptions {
-  enum class Alignment {
-    // By default all allocations will be aligned to 8B (16B if
-    // BUILDFLAG_INTERNAL_USE_PARTITION_ALLOC_AS_MALLOC is true).
-    kRegular,
-
-    // In addition to the above alignment enforcement, this option allows using
-    // AlignedAlloc() which can align at a larger boundary.  This option comes
-    // at a cost of disallowing cookies on Debug builds and tags/ref-counts for
-    // CheckedPtr. It also causes all allocations to go outside of GigaCage, so
-    // that CheckedPtr can easily tell if a pointer comes with a tag/ref-count
-    // or not.
-    kAlignedAlloc,
-  };
-
-  enum class ThreadCache {
-    kDisabled,
-    kEnabled,
-  };
-
-  enum class PCScan {
-    kDisabled,
-    kEnabled,
-  };
-
-  Alignment alignment = Alignment::kRegular;
-  ThreadCache thread_cache = ThreadCache::kDisabled;
-  PCScan pcscan = PCScan::kDisabled;
-};
-
-// Never instantiate a PartitionRoot directly, instead use
-// PartitionAllocator.
-template <bool thread_safe>
-struct BASE_EXPORT PartitionRoot {
-  using Page = internal::PartitionPage<thread_safe>;
-  using Bucket = internal::PartitionBucket<thread_safe>;
-  using SuperPageExtentEntry =
-      internal::PartitionSuperPageExtentEntry<thread_safe>;
-  using DirectMapExtent = internal::PartitionDirectMapExtent<thread_safe>;
-  using ScopedGuard = internal::ScopedGuard<thread_safe>;
-  using PCScan = base::Optional<internal::PCScan<thread_safe>>;
-
-  internal::MaybeSpinLock<thread_safe> lock_;
-
-  // Flags accessed on fast paths.
-  bool with_thread_cache = false;
-  const bool is_thread_safe = thread_safe;
-  // TODO(bartekn): Consider size of added extras (cookies and/or tag, or
-  // nothing) instead of true|false, so that we can just add or subtract the
-  // size instead of having an if branch on the hot paths.
-  bool allow_extras;
-  bool initialized = false;
-
-#if ENABLE_TAG_FOR_CHECKED_PTR2 || ENABLE_TAG_FOR_MTE_CHECKED_PTR
-  internal::PartitionTag current_partition_tag = 0;
-#endif
-#if ENABLE_TAG_FOR_MTE_CHECKED_PTR
-  char* next_tag_bitmap_page = nullptr;
-#endif
-
-  // Bookkeeping.
-  // Invariant: total_size_of_committed_pages <=
-  //                total_size_of_super_pages +
-  //                total_size_of_direct_mapped_pages.
-  size_t total_size_of_committed_pages GUARDED_BY(lock_) = 0;
-  size_t total_size_of_super_pages GUARDED_BY(lock_) = 0;
-  size_t total_size_of_direct_mapped_pages GUARDED_BY(lock_) = 0;
-
-  char* next_super_page = nullptr;
-  char* next_partition_page = nullptr;
-  char* next_partition_page_end = nullptr;
-  SuperPageExtentEntry* current_extent = nullptr;
-  SuperPageExtentEntry* first_extent = nullptr;
-  DirectMapExtent* direct_map_list = nullptr;
-  Page* global_empty_page_ring[kMaxFreeableSpans] = {};
-  int16_t global_empty_page_ring_index = 0;
-
-  // Integrity check = ~reinterpret_cast<uintptr_t>(this).
-  uintptr_t inverted_self = 0;
-  PCScan pcscan;
-
-  // The bucket lookup table lets us map a size_t to a bucket quickly.
-  // The trailing +1 caters for the overflow case for very large allocation
-  // sizes.  It is one flat array instead of a 2D array because in the 2D
-  // world, we'd need to index array[blah][max+1] which risks undefined
-  // behavior.
-  static uint16_t
-      bucket_index_lookup[((kBitsPerSizeT + 1) * kNumBucketsPerOrder) + 1];
-  // Accessed on fast paths, but sizeof(Bucket) is large, so there is no real
-  // benefit in packing it with other members.
-  Bucket buckets[kNumBuckets] = {};
-  Bucket sentinel_bucket;
-
-  PartitionRoot() = default;
-  explicit PartitionRoot(PartitionOptions opts) { Init(opts); }
-  ~PartitionRoot();
-
-  // Public API
-  //
-  // Allocates out of the given bucket. Properly, this function should probably
-  // be in PartitionBucket, but because the implementation needs to be inlined
-  // for performance, and because it needs to inspect PartitionPage,
-  // it becomes impossible to have it in PartitionBucket as this causes a
-  // cyclical dependency on PartitionPage function implementations.
-  //
-  // Moving it a layer lower couples PartitionRoot and PartitionBucket, but
-  // preserves the layering of the includes.
-  void Init(PartitionOptions);
-
-  ALWAYS_INLINE static bool IsValidPage(Page* page);
-  ALWAYS_INLINE static PartitionRoot* FromPage(Page* page);
-
-  ALWAYS_INLINE void IncreaseCommittedPages(size_t len)
-      EXCLUSIVE_LOCKS_REQUIRED(lock_);
-  ALWAYS_INLINE void DecreaseCommittedPages(size_t len)
-      EXCLUSIVE_LOCKS_REQUIRED(lock_);
-  ALWAYS_INLINE void DecommitSystemPages(void* address, size_t length)
-      EXCLUSIVE_LOCKS_REQUIRED(lock_);
-  ALWAYS_INLINE void RecommitSystemPages(void* address, size_t length)
-      EXCLUSIVE_LOCKS_REQUIRED(lock_);
-
-  NOINLINE void OutOfMemory(size_t size);
-
-  // Returns a pointer aligned on |alignement|, or nullptr.
-  //
-  // |alignment| has to be a power of two and a multiple of sizeof(void*) (as in
-  // posix_memalign() for POSIX systems). The returned pointer may include
-  // padding, and can be passed to |Free()| later.
-  //
-  // NOTE: Doesn't work when DCHECK_IS_ON(), as it is incompatible with cookies.
-  ALWAYS_INLINE void* AlignedAllocFlags(int flags,
-                                        size_t alignment,
-                                        size_t size);
-
-  ALWAYS_INLINE void* Alloc(size_t size, const char* type_name);
-  ALWAYS_INLINE void* AllocFlags(int flags, size_t size, const char* type_name);
-  // Same as |AllocFlags()|, but bypasses the allocator hooks.
-  //
-  // This is separate from AllocFlags() because other callers of AllocFlags()
-  // should not have the extra branch checking whether the hooks should be
-  // ignored or not. This is the same reason why |FreeNoHooks()|
-  // exists. However, |AlignedAlloc()| and |Realloc()| have few callers, so
-  // taking the extra branch in the non-malloc() case doesn't hurt. In addition,
-  // for the malloc() case, the compiler correctly removes the branch, since
-  // this is marked |ALWAYS_INLINE|.
-  ALWAYS_INLINE void* AllocFlagsNoHooks(int flags, size_t size);
-
-  ALWAYS_INLINE void* Realloc(void* ptr, size_t newize, const char* type_name);
-  // Overload that may return nullptr if reallocation isn't possible. In this
-  // case, |ptr| remains valid.
-  ALWAYS_INLINE void* TryRealloc(void* ptr,
-                                 size_t new_size,
-                                 const char* type_name);
-  NOINLINE void* ReallocFlags(int flags,
-                              void* ptr,
-                              size_t new_size,
-                              const char* type_name);
-  ALWAYS_INLINE static void Free(void* ptr);
-  // Same as |Free()|, bypasses the allocator hooks.
-  ALWAYS_INLINE static void FreeNoHooks(void* ptr);
-  // Immediately frees the pointer bypassing the quarantine.
-  ALWAYS_INLINE void FreeNoHooksImmediate(void* ptr, Page* page);
-
-  ALWAYS_INLINE static size_t GetUsableSize(void* ptr);
-  ALWAYS_INLINE size_t GetSize(void* ptr) const;
-  ALWAYS_INLINE size_t ActualSize(size_t size);
-
-  // Frees memory from this partition, if possible, by decommitting pages.
-  // |flags| is an OR of base::PartitionPurgeFlags.
-  void PurgeMemory(int flags);
-
-  void DumpStats(const char* partition_name,
-                 bool is_light_dump,
-                 PartitionStatsDumper* partition_stats_dumper);
-
-  static uint16_t SizeToBucketIndex(size_t size);
-
-  // Frees memory, with |ptr| as returned by |RawAlloc()|.
-  ALWAYS_INLINE void RawFree(void* ptr, Page* page);
-  static void RawFreeStatic(void* ptr);
-
-  internal::ThreadCache* thread_cache_for_testing() const {
-    return with_thread_cache ? internal::ThreadCache::Get() : nullptr;
-  }
-  size_t total_size_of_committed_pages_for_testing() {
-    ScopedGuard guard{lock_};
-    return total_size_of_committed_pages;
-  }
-
-  ALWAYS_INLINE internal::PartitionTag GetNewPartitionTag() {
-#if ENABLE_TAG_FOR_CHECKED_PTR2 || ENABLE_TAG_FOR_MTE_CHECKED_PTR
-    auto tag = ++current_partition_tag;
-    tag += !tag;  // Avoid 0.
-    current_partition_tag = tag;
-    return tag;
-#else
-    return 0;
-#endif
-  }
-
- private:
-  // Allocates memory, without any cookies / tags.
-  //
-  // |flags| and |size| are as in AllocFlags(). |allocated_size| and
-  // is_already_zeroed| are output only. |allocated_size| is guaranteed to be
-  // larger or equal to |size|.
-  ALWAYS_INLINE void* RawAlloc(Bucket* bucket,
-                               int flags,
-                               size_t size,
-                               size_t* allocated_size,
-                               bool* is_already_zeroed);
-  ALWAYS_INLINE void* AllocFromBucket(Bucket* bucket,
-                                      int flags,
-                                      size_t size,
-                                      size_t* allocated_size,
-                                      bool* is_already_zeroed)
-      EXCLUSIVE_LOCKS_REQUIRED(lock_);
-
-  bool ReallocDirectMappedInPlace(internal::PartitionPage<thread_safe>* page,
-                                  size_t requested_size)
-      EXCLUSIVE_LOCKS_REQUIRED(lock_);
-  void DecommitEmptyPages() EXCLUSIVE_LOCKS_REQUIRED(lock_);
-
-  friend class internal::ThreadCache;
-};
-
 template <bool thread_safe>
 ALWAYS_INLINE void* PartitionRoot<thread_safe>::AllocFromBucket(
     Bucket* bucket,
     int flags,
-    size_t size,
-    size_t* allocated_size,
+    size_t raw_size,
+    size_t* utilized_slot_size,
     bool* is_already_zeroed) {
   *is_already_zeroed = false;
 
@@ -611,7 +384,7 @@
   // Check that this page is neither full nor freed.
   PA_DCHECK(page);
   PA_DCHECK(page->num_allocated_slots >= 0);
-  *allocated_size = bucket->slot_size;
+  *utilized_slot_size = bucket->slot_size;
 
   void* ret = page->freelist_head;
   if (LIKELY(ret)) {
@@ -621,7 +394,7 @@
 
     // All large allocations must go through the slow path to correctly update
     // the size metadata.
-    PA_DCHECK(page->get_raw_size() == 0);
+    PA_DCHECK(!page->get_raw_size_ptr());  // doesn't have raw size
     internal::PartitionFreelistEntry* new_head =
         internal::EncodedPartitionFreelistEntry::Decode(
             page->freelist_head->next);
@@ -630,7 +403,7 @@
 
     PA_DCHECK(page->bucket == bucket);
   } else {
-    ret = bucket->SlowPathAlloc(this, flags, size, is_already_zeroed);
+    ret = bucket->SlowPathAlloc(this, flags, raw_size, is_already_zeroed);
     // TODO(palmer): See if we can afford to make this a CHECK.
     PA_DCHECK(!ret || IsValidPage(Page::FromPointer(ret)));
 
@@ -642,7 +415,7 @@
     PA_DCHECK((page->bucket == bucket) || (page->bucket->is_direct_mapped() &&
                                            (bucket == &sentinel_bucket)));
 
-    *allocated_size = page->GetAllocatedSize();
+    *utilized_slot_size = page->GetUtilizedSlotSize();
   }
 
   return ret;
@@ -706,23 +479,32 @@
   PA_DCHECK(page);
   PA_DCHECK(IsValidPage(page));
 
+#if DCHECK_IS_ON()
+  size_t utilized_slot_size = page->GetUtilizedSlotSize();
+#endif
+
   if (allow_extras) {
     // |ptr| points after the tag and the cookie.
-    // The layout is | tag or ref count | cookie | data | cookie |
-    //               ^                           ^
-    //      allocation_start_ptr                ptr
     //
-    // Note: tag, reference count and cookie can be 0-sized.
+    // Layout inside the slot:
+    //  <--------extras------->                  <-extras->
+    //  <----------------utilized_slot_size--------------->
+    //  |[tag/refcnt]|[cookie]|...data...|[empty]|[cookie]|[unused]|
+    //  ^                     ^
+    //  |                     |
+    //  allocation_start_ptr  ptr
+    //
+    // Note: tag, ref-count and cookie can be 0-sized.
+    //
+    // For more context, see the other "Layout inside the slot" comment below.
     void* allocation_start_ptr =
         internal::PartitionPointerAdjustSubtract(true /* allow_extras */, ptr);
 
 #if DCHECK_IS_ON()
-    size_t allocated_size = page->GetAllocatedSize();
-
     void* start_cookie_ptr =
         internal::PartitionCookiePointerAdjustSubtract(ptr);
     void* end_cookie_ptr = internal::PartitionCookiePointerAdjustSubtract(
-        reinterpret_cast<char*>(allocation_start_ptr) + allocated_size);
+        reinterpret_cast<char*>(allocation_start_ptr) + utilized_slot_size);
 
     // If these asserts fire, you probably corrupted memory.
     internal::PartitionCookieCheckValue(start_cookie_ptr);
@@ -732,9 +514,9 @@
     if (!page->bucket->is_direct_mapped()) {
       // PartitionTagIncrementValue and PartitionTagClearValue require that the
       // size is tag_bitmap::kBytesPerPartitionTag-aligned (currently 16
-      // bytes-aligned) when MTECheckedPtr is enabled. However, allocated_size
-      // may not be aligned for single-slot slot spans. So we need the bucket's
-      // slot_size.
+      // bytes-aligned) when MTECheckedPtr is enabled. However,
+      // utilized_slot_size may not be aligned for single-slot slot spans. So we
+      // need the bucket's slot_size.
       size_t slot_size_with_no_extras =
           internal::PartitionSizeAdjustSubtract(true, page->bucket->slot_size);
 #if ENABLE_TAG_FOR_MTE_CHECKED_PTR && MTE_CHECKED_PTR_SET_TAG_AT_FREE
@@ -751,9 +533,9 @@
       // potential use-after-free issues into unexploitable crashes.
       if (UNLIKELY(!ref_count->HasOneRef())) {
 #ifdef ADDRESS_SANITIZER
-        ASAN_POISON_MEMORY_REGION(ptr, size_with_no_extras);
+        ASAN_POISON_MEMORY_REGION(ptr, usable_size);
 #else
-        memset(ptr, kFreedByte, size_with_no_extras);
+        memset(ptr, kFreedByte, usable_size);
 #endif
         ref_count->Release();
         return;
@@ -765,7 +547,7 @@
   }
 
 #if DCHECK_IS_ON()
-  memset(ptr, kFreedByte, page->GetAllocatedSize());
+  memset(ptr, kFreedByte, utilized_slot_size);
 #endif
 
   // TLS access can be expensive, do a cheap local check first.
@@ -881,7 +663,7 @@
   Page* page = Page::FromPointerNoAlignmentCheck(ptr);
   auto* root = PartitionRoot<thread_safe>::FromPage(page);
 
-  size_t size = page->GetAllocatedSize();
+  size_t size = page->GetUtilizedSlotSize();
   // Adjust back by subtracing extras (if any).
   size = internal::PartitionSizeAdjustSubtract(root->allow_extras, size);
   return size;
@@ -934,16 +716,16 @@
 template <bool thread_safe>
 ALWAYS_INLINE void* PartitionRoot<thread_safe>::AllocFlags(
     int flags,
-    size_t size,
+    size_t requested_size,
     const char* type_name) {
   PA_DCHECK(flags < PartitionAllocLastFlag << 1);
   PA_DCHECK((flags & PartitionAllocNoHooks) == 0);  // Internal only.
   PA_DCHECK(initialized);
 
 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-  CHECK_MAX_SIZE_OR_RETURN_NULLPTR(size, flags);
+  CHECK_MAX_SIZE_OR_RETURN_NULLPTR(requested_size, flags);
   const bool zero_fill = flags & PartitionAllocZeroFill;
-  void* result = zero_fill ? calloc(1, size) : malloc(size);
+  void* result = zero_fill ? calloc(1, requested_size) : malloc(requested_size);
   PA_CHECK(result || flags & PartitionAllocReturnNull);
   return result;
 #else
@@ -951,18 +733,19 @@
   void* ret = nullptr;
   const bool hooks_enabled = PartitionAllocHooks::AreHooksEnabled();
   if (UNLIKELY(hooks_enabled)) {
-    if (PartitionAllocHooks::AllocationOverrideHookIfEnabled(&ret, flags, size,
-                                                             type_name)) {
-      PartitionAllocHooks::AllocationObserverHookIfEnabled(ret, size,
+    if (PartitionAllocHooks::AllocationOverrideHookIfEnabled(
+            &ret, flags, requested_size, type_name)) {
+      PartitionAllocHooks::AllocationObserverHookIfEnabled(ret, requested_size,
                                                            type_name);
       return ret;
     }
   }
 
-  ret = AllocFlagsNoHooks(flags, size);
+  ret = AllocFlagsNoHooks(flags, requested_size);
 
   if (UNLIKELY(hooks_enabled)) {
-    PartitionAllocHooks::AllocationObserverHookIfEnabled(ret, size, type_name);
+    PartitionAllocHooks::AllocationObserverHookIfEnabled(ret, requested_size,
+                                                         type_name);
   }
 
   return ret;
@@ -970,24 +753,25 @@
 }
 
 template <bool thread_safe>
-ALWAYS_INLINE void* PartitionRoot<thread_safe>::AllocFlagsNoHooks(int flags,
-                                                                  size_t size) {
+ALWAYS_INLINE void* PartitionRoot<thread_safe>::AllocFlagsNoHooks(
+    int flags,
+    size_t requested_size) {
   // The thread cache is added "in the middle" of the main allocator, that is:
   // - After all the cookie/tag management
   // - Before the "raw" allocator.
   //
   // That is, the general allocation flow is:
-  // 1. Adjustment of requested size to make room for tags / cookies
+  // 1. Adjustment of requested size to make room for extras
   // 2. Allocation:
   //   a. Call to the thread cache, if it succeeds, go to step 3.
   //   b. Otherwise, call the "raw" allocator <-- Locking
   // 3. Handle cookies/tags, zero allocation if required
-  size_t requested_size = size;
-  size = internal::PartitionSizeAdjustAdd(allow_extras, size);
-  PA_CHECK(size >= requested_size);  // check for overflows
+  size_t raw_size =
+      internal::PartitionSizeAdjustAdd(allow_extras, requested_size);
+  PA_CHECK(raw_size >= requested_size);  // check for overflows
 
-  uint16_t bucket_index = SizeToBucketIndex(size);
-  size_t allocated_size;
+  uint16_t bucket_index = SizeToBucketIndex(raw_size);
+  size_t utilized_slot_size;
   bool is_already_zeroed;
   void* ret = nullptr;
 
@@ -1023,13 +807,16 @@
     // the thread cache allocation will return nullptr.
     ret = tcache->GetFromCache(bucket_index);
     is_already_zeroed = false;
-    allocated_size = buckets[bucket_index].slot_size;
+    utilized_slot_size = buckets[bucket_index].slot_size;
 
 #if DCHECK_IS_ON()
     // Make sure that the allocated pointer comes from the same place it would
     // for a non-thread cache allocation.
     if (ret) {
       Page* page = Page::FromPointerNoAlignmentCheck(ret);
+      // All large allocations must go through the RawAlloc path to correctly
+      // set |utilized_slot_size|.
+      PA_DCHECK(!page->get_raw_size_ptr());  // doesn't have raw size
       PA_DCHECK(IsValidPage(page));
       PA_DCHECK(page->bucket == &buckets[bucket_index]);
     }
@@ -1037,26 +824,44 @@
   }
 
   if (!ret)
-    ret = RawAlloc(buckets + bucket_index, flags, size, &allocated_size,
+    ret = RawAlloc(buckets + bucket_index, flags, raw_size, &utilized_slot_size,
                    &is_already_zeroed);
 
   if (UNLIKELY(!ret))
     return nullptr;
 
-  // Layout inside the slot: |[tag]|cookie|object|[empty]|cookie|
-  //                                      <--a--->
-  //                                      <------b------->
-  //                         <-----------------c---------------->
-  //   a: allocated_size
-  //   b: size_with_no_extras
-  //   c: new_slot_size
-  // Note, empty space occurs if the slot size is larger than needed to
-  // accommodate the request. This doesn't apply to direct-mapped allocations
-  // and single-slot spans.
-  // The tag may or may not exist in the slot, depending on CheckedPtr
-  // implementation.
-  size_t size_with_no_extras =
-      internal::PartitionSizeAdjustSubtract(allow_extras, allocated_size);
+  // Layout inside the slot:
+  //  |[tag/refcnt]|[cookie]|...data...|[empty]|[cookie]|[unused]|
+  //                        <----a----->
+  //                        <--------b--------->
+  //  <----------c---------->                  <---c---->
+  //  <---------------d--------------->   +    <---d---->
+  //  <------------------------e------------------------>
+  //  <----------------------------f----------------------------->
+  //   a: requested_size
+  //   b: usable_size
+  //   c: extras
+  //   d: raw_size
+  //   e: utilized_slot_size
+  //   f: slot_size
+  //
+  // - The tag/ref-count may or may not exist in the slot, depending on
+  //   CheckedPtr implementation.
+  // - Cookies exist only when DCHECK is on.
+  // - Think of raw_size as the minimum size required internally to satisfy
+  //   the allocation request (i.e. requested_size + extras)
+  // - Note, at most one "empty" or "unused" space can occur at a time. It
+  //   occurs when slot_size is larger than raw_size. "unused" applies only to
+  //   large allocations (direct-mapped and single-slot slot spans) and "empty"
+  //   only to small allocations.
+  //   Why either-or, one might ask? We make an effort to put the trailing
+  //   cookie as close to data as possible to catch overflows (often
+  //   off-by-one), but that's possible only if we have enough space in metadata
+  //   to save raw_size, i.e. only for large allocations. For small allocations,
+  //   we have no other choice than putting the cookie at the very end of the
+  //   slot, thus creating the "empty" space.
+  size_t usable_size =
+      internal::PartitionSizeAdjustSubtract(allow_extras, utilized_slot_size);
   // The value given to the application is just after the tag and cookie.
   ret = internal::PartitionPointerAdjustAdd(allow_extras, ret);
 
@@ -1065,7 +870,7 @@
   if (allow_extras) {
     char* char_ret = static_cast<char*>(ret);
     internal::PartitionCookieWriteValue(char_ret - internal::kCookieSize);
-    internal::PartitionCookieWriteValue(char_ret + size_with_no_extras);
+    internal::PartitionCookieWriteValue(char_ret + usable_size);
   }
 #endif
 
@@ -1074,21 +879,21 @@
   bool zero_fill = flags & PartitionAllocZeroFill;
   if (!zero_fill) {
 #if DCHECK_IS_ON()
-    memset(ret, kUninitializedByte, size_with_no_extras);
+    memset(ret, kUninitializedByte, usable_size);
 #endif
   } else if (!is_already_zeroed) {
-    memset(ret, 0, size_with_no_extras);
+    memset(ret, 0, usable_size);
   }
 
-  bool is_direct_mapped = size > kMaxBucketed;
+  bool is_direct_mapped = raw_size > kMaxBucketed;
   if (allow_extras && !is_direct_mapped) {
     // Do not set tag for MTECheckedPtr in the set-tag-at-free case.
     // It is set only at Free() time and at slot span allocation time.
 #if !ENABLE_TAG_FOR_MTE_CHECKED_PTR || !MTE_CHECKED_PTR_SET_TAG_AT_FREE
     // PartitionTagSetValue requires that the size is
     // tag_bitmap::kBytesPerPartitionTag-aligned (currently 16 bytes-aligned)
-    // when MTECheckedPtr is enabled. However, allocated_size may not be aligned
-    // for single-slot slot spans. So we need the bucket's slot_size.
+    // when MTECheckedPtr is enabled. However, utilized_slot_size may not be
+    // aligned for single-slot slot spans. So we need the bucket's slot_size.
     size_t slot_size_with_no_extras = internal::PartitionSizeAdjustSubtract(
         allow_extras, buckets[bucket_index].slot_size);
     internal::PartitionTagSetValue(ret, slot_size_with_no_extras,
@@ -1106,11 +911,11 @@
 ALWAYS_INLINE void* PartitionRoot<thread_safe>::RawAlloc(
     Bucket* bucket,
     int flags,
-    size_t size,
-    size_t* allocated_size,
+    size_t raw_size,
+    size_t* utilized_slot_size,
     bool* is_already_zeroed) {
   internal::ScopedGuard<thread_safe> guard{lock_};
-  return AllocFromBucket(bucket, flags, size, allocated_size,
+  return AllocFromBucket(bucket, flags, raw_size, utilized_slot_size,
                          is_already_zeroed);
 }
 
@@ -1166,9 +971,9 @@
 }
 
 template <bool thread_safe>
-ALWAYS_INLINE void* PartitionRoot<thread_safe>::Alloc(size_t size,
+ALWAYS_INLINE void* PartitionRoot<thread_safe>::Alloc(size_t requested_size,
                                                       const char* type_name) {
-  return AllocFlags(0, size, type_name);
+  return AllocFlags(0, requested_size, type_name);
 }
 
 template <bool thread_safe>
diff --git a/base/allocator/partition_allocator/partition_bucket.cc b/base/allocator/partition_allocator/partition_bucket.cc
index 1748c71..3c97793 100644
--- a/base/allocator/partition_allocator/partition_bucket.cc
+++ b/base/allocator/partition_allocator/partition_bucket.cc
@@ -543,7 +543,7 @@
 void* PartitionBucket<thread_safe>::SlowPathAlloc(
     PartitionRoot<thread_safe>* root,
     int flags,
-    size_t size,
+    size_t raw_size,
     bool* is_already_zeroed) {
   // The slow path is called when the freelist is empty.
   PA_DCHECK(!active_pages_head->freelist_head);
@@ -567,11 +567,11 @@
   // the empty or decommitted lists which affects the subsequent conditional.
   bool return_null = flags & PartitionAllocReturnNull;
   if (UNLIKELY(is_direct_mapped())) {
-    PA_DCHECK(size > kMaxBucketed);
+    PA_DCHECK(raw_size > kMaxBucketed);
     PA_DCHECK(this == &root->sentinel_bucket);
     PA_DCHECK(active_pages_head ==
               PartitionPage<thread_safe>::get_sentinel_page());
-    if (size > MaxDirectMapped()) {
+    if (raw_size > MaxDirectMapped()) {
       if (return_null)
         return nullptr;
       // The lock is here to protect PA from:
@@ -596,10 +596,10 @@
       // equivalent, but that's violating the contract of
       // base::OnNoMemoryInternal().
       ScopedUnlockGuard<thread_safe> unlock{root->lock_};
-      PartitionExcessiveAllocationSize(size);
+      PartitionExcessiveAllocationSize(raw_size);
       IMMEDIATE_CRASH();  // Not required, kept as documentation.
     }
-    new_page = PartitionDirectMap(root, flags, size);
+    new_page = PartitionDirectMap(root, flags, raw_size);
     if (new_page)
       new_page_bucket = new_page->bucket;
     // New pages from PageAllocator are always zeroed.
@@ -659,13 +659,13 @@
       return nullptr;
     // See comment above.
     ScopedUnlockGuard<thread_safe> unlock{root->lock_};
-    root->OutOfMemory(size);
+    root->OutOfMemory(raw_size);
     IMMEDIATE_CRASH();  // Not required, kept as documentation.
   }
 
   PA_DCHECK(new_page_bucket != &root->sentinel_bucket);
   new_page_bucket->active_pages_head = new_page;
-  new_page->set_raw_size(size);
+  new_page->set_raw_size(raw_size);
 
   // If we found an active page with free slots, or an empty page, we have a
   // usable freelist head.
diff --git a/base/allocator/partition_allocator/partition_bucket.h b/base/allocator/partition_allocator/partition_bucket.h
index 37f44cdf..2bada01 100644
--- a/base/allocator/partition_allocator/partition_bucket.h
+++ b/base/allocator/partition_allocator/partition_bucket.h
@@ -60,7 +60,7 @@
   // Note the matching Free() functions are in PartitionPage.
   BASE_EXPORT NOINLINE void* SlowPathAlloc(PartitionRoot<thread_safe>* root,
                                            int flags,
-                                           size_t size,
+                                           size_t raw_size,
                                            bool* is_already_zeroed)
       EXCLUSIVE_LOCKS_REQUIRED(root->lock_);
 
diff --git a/base/allocator/partition_allocator/partition_page.h b/base/allocator/partition_allocator/partition_page.h
index 5044433a..a3c7fbd 100644
--- a/base/allocator/partition_allocator/partition_page.h
+++ b/base/allocator/partition_allocator/partition_page.h
@@ -123,14 +123,14 @@
   ALWAYS_INLINE static PartitionPage* FromPointerNoAlignmentCheck(void* ptr);
   ALWAYS_INLINE static PartitionPage* FromPointer(void* ptr);
 
-  // Returns either the exact allocated size for direct-mapped and single-slot
-  // buckets, or the slot size. The second one is an overestimate of the real
-  // allocated size.
-  ALWAYS_INLINE size_t GetAllocatedSize() const {
-    // Allocated size can be:
+  // Returns size of the region used within a slot. The used region comprises
+  // of actual allocated data, extras and possibly empty space.
+  ALWAYS_INLINE size_t GetUtilizedSlotSize() const {
+    // The returned size can be:
     // - The slot size for small buckets.
-    // - Stored exactly, for large buckets and direct-mapped allocations (see
-    // the comment in get_raw_size_ptr()).
+    // - Exact needed size to satisfy allocation (incl. extras), for large
+    //   buckets and direct-mapped allocations (see the comment in
+    //   get_raw_size_ptr() for more info).
     size_t result = bucket->slot_size;
     if (UNLIKELY(get_raw_size_ptr()))  // has raw size.
       result = get_raw_size();
@@ -274,8 +274,8 @@
     const {
   // For direct-map as well as single-slot buckets which span more than
   // |kMaxPartitionPagesPerSlotSpan| partition pages, we have some spare
-  // metadata space to store the raw allocation size. We can use this to report
-  // better statistics.
+  // metadata space to store the raw size needed to satisfy the allocation
+  // (requested size + extras). We can use this to report better statistics.
   if (LIKELY(bucket->slot_size <=
              MaxSystemPagesPerSlotSpan() * SystemPageSize()))
     return nullptr;
diff --git a/base/allocator/partition_allocator/partition_ref_count.cc b/base/allocator/partition_allocator/partition_ref_count.cc
index 10a1dc4d..c571447 100644
--- a/base/allocator/partition_allocator/partition_ref_count.cc
+++ b/base/allocator/partition_allocator/partition_ref_count.cc
@@ -21,13 +21,13 @@
   auto* root = PartitionRoot<ThreadSafe>::FromPage(page);
 
 #ifdef ADDRESS_SANITIZER
-  size_t allocated_size = page->GetAllocatedSize();
+  size_t utilized_slot_size = page->GetUtilizedSlotSize();
   // PartitionRefCount is required to be allocated inside a `PartitionRoot` that
   // supports extras.
   PA_DCHECK(root->allow_extras);
-  size_t size_with_no_extras = internal::PartitionSizeAdjustSubtract(
-      /* allow_extras= */ true, allocated_size);
-  ASAN_UNPOISON_MEMORY_REGION(this, size_with_no_extras);
+  size_t usable_size = internal::PartitionSizeAdjustSubtract(
+      /* allow_extras= */ true, utilized_slot_size);
+  ASAN_UNPOISON_MEMORY_REGION(this, usable_size);
 #endif
 
   if (root->is_thread_safe) {
diff --git a/base/allocator/partition_allocator/partition_root.h b/base/allocator/partition_allocator/partition_root.h
new file mode 100644
index 0000000..751bce59
--- /dev/null
+++ b/base/allocator/partition_allocator/partition_root.h
@@ -0,0 +1,254 @@
+// Copyright (c) 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 BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ROOT_H_
+#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ROOT_H_
+
+#include "base/allocator/partition_allocator/partition_alloc_constants.h"
+#include "base/allocator/partition_allocator/partition_alloc_forward.h"
+#include "base/allocator/partition_allocator/partition_direct_map_extent.h"
+#include "base/allocator/partition_allocator/partition_lock.h"
+#include "base/allocator/partition_allocator/partition_tag.h"
+#include "base/allocator/partition_allocator/pcscan.h"
+#include "base/allocator/partition_allocator/thread_cache.h"
+
+namespace base {
+
+class PartitionStatsDumper;
+
+// Options struct used to configure PartitionRoot and PartitionAllocator.
+struct PartitionOptions {
+  enum class Alignment {
+    // By default all allocations will be aligned to 8B (16B if
+    // BUILDFLAG_INTERNAL_USE_PARTITION_ALLOC_AS_MALLOC is true).
+    kRegular,
+
+    // In addition to the above alignment enforcement, this option allows using
+    // AlignedAlloc() which can align at a larger boundary.  This option comes
+    // at a cost of disallowing cookies on Debug builds and tags/ref-counts for
+    // CheckedPtr. It also causes all allocations to go outside of GigaCage, so
+    // that CheckedPtr can easily tell if a pointer comes with a tag/ref-count
+    // or not.
+    kAlignedAlloc,
+  };
+
+  enum class ThreadCache {
+    kDisabled,
+    kEnabled,
+  };
+
+  enum class PCScan {
+    kDisabled,
+    kEnabled,
+  };
+
+  Alignment alignment = Alignment::kRegular;
+  ThreadCache thread_cache = ThreadCache::kDisabled;
+  PCScan pcscan = PCScan::kDisabled;
+};
+
+// Never instantiate a PartitionRoot directly, instead use
+// PartitionAllocator.
+template <bool thread_safe>
+struct BASE_EXPORT PartitionRoot {
+  using Page = internal::PartitionPage<thread_safe>;
+  using Bucket = internal::PartitionBucket<thread_safe>;
+  using SuperPageExtentEntry =
+      internal::PartitionSuperPageExtentEntry<thread_safe>;
+  using DirectMapExtent = internal::PartitionDirectMapExtent<thread_safe>;
+  using ScopedGuard = internal::ScopedGuard<thread_safe>;
+  using PCScan = base::Optional<internal::PCScan<thread_safe>>;
+
+  internal::MaybeSpinLock<thread_safe> lock_;
+
+  // Flags accessed on fast paths.
+  bool with_thread_cache = false;
+  const bool is_thread_safe = thread_safe;
+  // TODO(bartekn): Consider size of added extras (cookies and/or tag, or
+  // nothing) instead of true|false, so that we can just add or subtract the
+  // size instead of having an if branch on the hot paths.
+  bool allow_extras;
+  bool initialized = false;
+
+#if ENABLE_TAG_FOR_CHECKED_PTR2 || ENABLE_TAG_FOR_MTE_CHECKED_PTR
+  internal::PartitionTag current_partition_tag = 0;
+#endif
+#if ENABLE_TAG_FOR_MTE_CHECKED_PTR
+  char* next_tag_bitmap_page = nullptr;
+#endif
+
+  // Bookkeeping.
+  // Invariant: total_size_of_committed_pages <=
+  //                total_size_of_super_pages +
+  //                total_size_of_direct_mapped_pages.
+  size_t total_size_of_committed_pages GUARDED_BY(lock_) = 0;
+  size_t total_size_of_super_pages GUARDED_BY(lock_) = 0;
+  size_t total_size_of_direct_mapped_pages GUARDED_BY(lock_) = 0;
+
+  char* next_super_page = nullptr;
+  char* next_partition_page = nullptr;
+  char* next_partition_page_end = nullptr;
+  SuperPageExtentEntry* current_extent = nullptr;
+  SuperPageExtentEntry* first_extent = nullptr;
+  DirectMapExtent* direct_map_list = nullptr;
+  Page* global_empty_page_ring[kMaxFreeableSpans] = {};
+  int16_t global_empty_page_ring_index = 0;
+
+  // Integrity check = ~reinterpret_cast<uintptr_t>(this).
+  uintptr_t inverted_self = 0;
+  PCScan pcscan;
+
+  // The bucket lookup table lets us map a size_t to a bucket quickly.
+  // The trailing +1 caters for the overflow case for very large allocation
+  // sizes.  It is one flat array instead of a 2D array because in the 2D
+  // world, we'd need to index array[blah][max+1] which risks undefined
+  // behavior.
+  static uint16_t
+      bucket_index_lookup[((kBitsPerSizeT + 1) * kNumBucketsPerOrder) + 1];
+  // Accessed on fast paths, but sizeof(Bucket) is large, so there is no real
+  // benefit in packing it with other members.
+  Bucket buckets[kNumBuckets] = {};
+  Bucket sentinel_bucket;
+
+  PartitionRoot() = default;
+  explicit PartitionRoot(PartitionOptions opts) { Init(opts); }
+  ~PartitionRoot();
+
+  // Public API
+  //
+  // Allocates out of the given bucket. Properly, this function should probably
+  // be in PartitionBucket, but because the implementation needs to be inlined
+  // for performance, and because it needs to inspect PartitionPage,
+  // it becomes impossible to have it in PartitionBucket as this causes a
+  // cyclical dependency on PartitionPage function implementations.
+  //
+  // Moving it a layer lower couples PartitionRoot and PartitionBucket, but
+  // preserves the layering of the includes.
+  void Init(PartitionOptions);
+
+  ALWAYS_INLINE static bool IsValidPage(Page* page);
+  ALWAYS_INLINE static PartitionRoot* FromPage(Page* page);
+
+  ALWAYS_INLINE void IncreaseCommittedPages(size_t len)
+      EXCLUSIVE_LOCKS_REQUIRED(lock_);
+  ALWAYS_INLINE void DecreaseCommittedPages(size_t len)
+      EXCLUSIVE_LOCKS_REQUIRED(lock_);
+  ALWAYS_INLINE void DecommitSystemPages(void* address, size_t length)
+      EXCLUSIVE_LOCKS_REQUIRED(lock_);
+  ALWAYS_INLINE void RecommitSystemPages(void* address, size_t length)
+      EXCLUSIVE_LOCKS_REQUIRED(lock_);
+
+  NOINLINE void OutOfMemory(size_t size);
+
+  // Returns a pointer aligned on |alignment|, or nullptr.
+  //
+  // |alignment| has to be a power of two and a multiple of sizeof(void*) (as in
+  // posix_memalign() for POSIX systems). The returned pointer may include
+  // padding, and can be passed to |Free()| later.
+  //
+  // NOTE: Doesn't work when DCHECK_IS_ON(), as it is incompatible with cookies.
+  ALWAYS_INLINE void* AlignedAllocFlags(int flags,
+                                        size_t alignment,
+                                        size_t size);
+
+  ALWAYS_INLINE void* Alloc(size_t requested_size, const char* type_name);
+  ALWAYS_INLINE void* AllocFlags(int flags,
+                                 size_t requested_size,
+                                 const char* type_name);
+  // Same as |AllocFlags()|, but bypasses the allocator hooks.
+  //
+  // This is separate from AllocFlags() because other callers of AllocFlags()
+  // should not have the extra branch checking whether the hooks should be
+  // ignored or not. This is the same reason why |FreeNoHooks()|
+  // exists. However, |AlignedAlloc()| and |Realloc()| have few callers, so
+  // taking the extra branch in the non-malloc() case doesn't hurt. In addition,
+  // for the malloc() case, the compiler correctly removes the branch, since
+  // this is marked |ALWAYS_INLINE|.
+  ALWAYS_INLINE void* AllocFlagsNoHooks(int flags, size_t requested_size);
+
+  ALWAYS_INLINE void* Realloc(void* ptr, size_t newize, const char* type_name);
+  // Overload that may return nullptr if reallocation isn't possible. In this
+  // case, |ptr| remains valid.
+  ALWAYS_INLINE void* TryRealloc(void* ptr,
+                                 size_t new_size,
+                                 const char* type_name);
+  NOINLINE void* ReallocFlags(int flags,
+                              void* ptr,
+                              size_t new_size,
+                              const char* type_name);
+  ALWAYS_INLINE static void Free(void* ptr);
+  // Same as |Free()|, bypasses the allocator hooks.
+  ALWAYS_INLINE static void FreeNoHooks(void* ptr);
+  // Immediately frees the pointer bypassing the quarantine.
+  ALWAYS_INLINE void FreeNoHooksImmediate(void* ptr, Page* page);
+
+  ALWAYS_INLINE static size_t GetUsableSize(void* ptr);
+  ALWAYS_INLINE size_t GetSize(void* ptr) const;
+  ALWAYS_INLINE size_t ActualSize(size_t size);
+
+  // Frees memory from this partition, if possible, by decommitting pages.
+  // |flags| is an OR of base::PartitionPurgeFlags.
+  void PurgeMemory(int flags);
+
+  void DumpStats(const char* partition_name,
+                 bool is_light_dump,
+                 PartitionStatsDumper* partition_stats_dumper);
+
+  static uint16_t SizeToBucketIndex(size_t size);
+
+  // Frees memory, with |ptr| as returned by |RawAlloc()|.
+  ALWAYS_INLINE void RawFree(void* ptr, Page* page);
+  static void RawFreeStatic(void* ptr);
+
+  internal::ThreadCache* thread_cache_for_testing() const {
+    return with_thread_cache ? internal::ThreadCache::Get() : nullptr;
+  }
+  size_t total_size_of_committed_pages_for_testing() {
+    ScopedGuard guard{lock_};
+    return total_size_of_committed_pages;
+  }
+
+  ALWAYS_INLINE internal::PartitionTag GetNewPartitionTag() {
+#if ENABLE_TAG_FOR_CHECKED_PTR2 || ENABLE_TAG_FOR_MTE_CHECKED_PTR
+    auto tag = ++current_partition_tag;
+    tag += !tag;  // Avoid 0.
+    current_partition_tag = tag;
+    return tag;
+#else
+    return 0;
+#endif
+  }
+
+ private:
+  // Allocates memory, without initializing extras.
+  //
+  // - |flags| are as in AllocFlags().
+  // - |raw_size| should accommodate extras on top of AllocFlags()'s
+  //   |requested_size|.
+  // - |utilized_slot_size| and |is_already_zeroed| are output only.
+  //   |utilized_slot_size| is guaranteed to be larger or equal to
+  //   |raw_size|.
+  ALWAYS_INLINE void* RawAlloc(Bucket* bucket,
+                               int flags,
+                               size_t raw_size,
+                               size_t* utilized_slot_size,
+                               bool* is_already_zeroed);
+  ALWAYS_INLINE void* AllocFromBucket(Bucket* bucket,
+                                      int flags,
+                                      size_t raw_size,
+                                      size_t* utilized_slot_size,
+                                      bool* is_already_zeroed)
+      EXCLUSIVE_LOCKS_REQUIRED(lock_);
+
+  bool ReallocDirectMappedInPlace(internal::PartitionPage<thread_safe>* page,
+                                  size_t requested_size)
+      EXCLUSIVE_LOCKS_REQUIRED(lock_);
+  void DecommitEmptyPages() EXCLUSIVE_LOCKS_REQUIRED(lock_);
+
+  friend class internal::ThreadCache;
+};
+
+}  // namespace base
+
+#endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ROOT_H_
diff --git a/base/allocator/partition_allocator/pcscan.cc b/base/allocator/partition_allocator/pcscan.cc
index 70e3a15..ef69fb2 100644
--- a/base/allocator/partition_allocator/pcscan.cc
+++ b/base/allocator/partition_allocator/pcscan.cc
@@ -180,10 +180,10 @@
       Page::FromPointerNoAlignmentCheck(reinterpret_cast<void*>(base));
   PA_DCHECK(&root_ == PartitionRoot<thread_safe>::FromPage(target_page));
 
-  const size_t object_size = PartitionSizeAdjustSubtract(
-      root_.allow_extras, target_page->GetAllocatedSize());
+  const size_t usable_size = PartitionSizeAdjustSubtract(
+      root_.allow_extras, target_page->GetUtilizedSlotSize());
   // Range check for inner pointers.
-  if (maybe_ptr >= base + object_size)
+  if (maybe_ptr >= base + usable_size)
     return 0;
 
   // Now we are certain that |maybe_ptr| is a dangling pointer. Mark it again in
@@ -208,9 +208,9 @@
       auto* page = Page::FromPointerNoAlignmentCheck(object);
       // Use zero as a zapping value to speed up the fast bailout check in
       // ScanPartition.
-      memset(
-          object, 0,
-          PartitionSizeAdjustSubtract(allow_extras, page->GetAllocatedSize()));
+      memset(object, 0,
+             PartitionSizeAdjustSubtract(allow_extras,
+                                         page->GetUtilizedSlotSize()));
     });
   }
 }
diff --git a/base/allocator/partition_allocator/thread_cache.cc b/base/allocator/partition_allocator/thread_cache.cc
index 9d0f6d26..f5f193f 100644
--- a/base/allocator/partition_allocator/thread_cache.cc
+++ b/base/allocator/partition_allocator/thread_cache.cc
@@ -130,7 +130,7 @@
   //
   // This also means that deallocation must use RawFreeStatic(), hence the
   // operator delete() implementation below.
-  size_t allocated_size;
+  size_t utilized_slot_size;
   bool already_zeroed;
 
   auto* bucket =
@@ -138,7 +138,7 @@
                           sizeof(ThreadCache));
   void* buffer =
       root->RawAlloc(bucket, PartitionAllocZeroFill, sizeof(ThreadCache),
-                     &allocated_size, &already_zeroed);
+                     &utilized_slot_size, &already_zeroed);
   ThreadCache* tcache = new (buffer) ThreadCache(root);
 
   // This may allocate.
diff --git a/base/allocator/partition_allocator/thread_cache_unittest.cc b/base/allocator/partition_allocator/thread_cache_unittest.cc
index a6716af..ed7671c 100644
--- a/base/allocator/partition_allocator/thread_cache_unittest.cc
+++ b/base/allocator/partition_allocator/thread_cache_unittest.cc
@@ -312,11 +312,11 @@
   EXPECT_EQ(10u, cache_fill_misses_counter.Delta());
 
   // Memory footprint.
-  size_t allocated_size = g_root->buckets[bucket_index].slot_size;
   ThreadCacheStats stats;
   ThreadCacheRegistry::Instance().DumpStats(true, &stats);
-  EXPECT_EQ(allocated_size * ThreadCache::kMaxCountPerBucket,
-            stats.bucket_total_memory);
+  EXPECT_EQ(
+      g_root->buckets[bucket_index].slot_size * ThreadCache::kMaxCountPerBucket,
+      stats.bucket_total_memory);
   EXPECT_EQ(sizeof(ThreadCache), stats.metadata_overhead);
 }
 
@@ -332,9 +332,9 @@
 
     ThreadCacheStats stats;
     ThreadCacheRegistry::Instance().DumpStats(false, &stats);
-    size_t allocated_size = g_root->buckets[bucket_index].slot_size;
     // 2* for this thread and the parent one.
-    EXPECT_EQ(2 * allocated_size, stats.bucket_total_memory);
+    EXPECT_EQ(2 * g_root->buckets[bucket_index].slot_size,
+              stats.bucket_total_memory);
     EXPECT_EQ(2 * sizeof(ThreadCache), stats.metadata_overhead);
 
     uint64_t this_thread_alloc_count =
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index b53876c..a1b08a4 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20201012.2.1
+0.20201012.3.3
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index b53876c..a1b08a4 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20201012.2.1
+0.20201012.3.3
diff --git a/build/fuchsia/update_images.py b/build/fuchsia/update_images.py
index bdc1140..165ae77b 100755
--- a/build/fuchsia/update_images.py
+++ b/build/fuchsia/update_images.py
@@ -48,12 +48,12 @@
   return images_to_download
 
 
-def DownloadSdkBootImages(bucket, sdk_hash, boot_image_names, image_output_dir):
+def DownloadSdkBootImages(bucket, sdk_hash, boot_image_names, image_root_dir):
   images_to_download = GetAllImages(boot_image_names)
   for image_to_download in images_to_download:
     device_type = image_to_download[0]
     arch = image_to_download[1]
-    image_output_dir = os.path.join(image_output_dir, arch, device_type)
+    image_output_dir = os.path.join(image_root_dir, arch, device_type)
     if os.path.exists(image_output_dir):
       continue
 
diff --git a/chrome/VERSION b/chrome/VERSION
index 412f1d2..3581564 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=88
 MINOR=0
-BUILD=4291
+BUILD=4292
 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 9d0ef2a..fc62ea3 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -156,6 +156,7 @@
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemRow.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java",
+  "java/src/org/chromium/chrome/browser/bookmarks/BookmarkListEntry.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkModel.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java
index 7dc2f902..8c802c2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java
@@ -10,7 +10,6 @@
 import android.view.MotionEvent;
 import android.view.ViewGroup;
 
-import androidx.annotation.IntDef;
 import androidx.annotation.LayoutRes;
 import androidx.annotation.VisibleForTesting;
 import androidx.recyclerview.widget.RecyclerView;
@@ -20,6 +19,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver;
+import org.chromium.chrome.browser.bookmarks.BookmarkListEntry.ViewType;
 import org.chromium.chrome.browser.bookmarks.BookmarkRow.Location;
 import org.chromium.chrome.browser.signin.PersonalizedSigninPromoView;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
@@ -28,41 +28,23 @@
 import org.chromium.components.browser_ui.widget.dragreorder.DragReorderableListAdapter;
 import org.chromium.components.browser_ui.widget.highlight.ViewHighlighter;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 
 /**
  * BaseAdapter for {@link RecyclerView}. It manages bookmarks to list there.
  */
-class BookmarkItemsAdapter extends DragReorderableListAdapter<BookmarkItem>
+class BookmarkItemsAdapter extends DragReorderableListAdapter<BookmarkListEntry>
         implements BookmarkUIObserver, ProfileSyncService.SyncStateChangedListener {
-    /**
-     * Specifies the view types that the bookmark delegate screen can contain.
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({ViewType.INVALID_PROMO, ViewType.PERSONALIZED_SIGNIN_PROMO,
-            ViewType.PERSONALIZED_SYNC_PROMO, ViewType.SYNC_PROMO, ViewType.FOLDER,
-            ViewType.BOOKMARK})
-    private @interface ViewType {
-        int INVALID_PROMO = -1;
-        int PERSONALIZED_SIGNIN_PROMO = 0;
-        int PERSONALIZED_SYNC_PROMO = 1;
-        int SYNC_PROMO = 2;
-        int FOLDER = 3;
-        int BOOKMARK = 4;
-    }
-
     private static final int MAXIMUM_NUMBER_OF_SEARCH_RESULTS = 500;
     private static final String EMPTY_QUERY = null;
 
     private final List<BookmarkId> mTopLevelFolders = new ArrayList<>();
 
     // There can only be one promo header at a time. This takes on one of the values:
-    // ViewType.PERSONALIZED_SIGNIN_PROMO, ViewType.SYNC_PROMO, or ViewType.INVALID_PROMO
+    // ViewType.PERSONALIZED_SIGNIN_PROMO, ViewType.SYNC_PROMO, or ViewType.INVALID.
     @ViewType
-    private int mPromoHeaderType = ViewType.INVALID_PROMO;
+    private int mPromoHeaderType = ViewType.INVALID;
     private BookmarkDelegate mDelegate;
     private BookmarkPromoHeader mPromoHeaderManager;
     private String mSearchText;
@@ -140,10 +122,14 @@
         clearHighlight();
         mElements.clear();
         // Restore the header, if it exists, then update it.
-        if (hasPromoHeader()) mElements.add(null);
+        if (hasPromoHeader()) {
+            mElements.add(BookmarkListEntry.createSyncPromoHeader(mPromoHeaderType));
+        }
+
         updateHeader(false);
         for (BookmarkId bId : bookmarks) {
-            mElements.add(mDelegate.getModel().getBookmarkById(bId));
+            BookmarkItem item = mDelegate.getModel().getBookmarkById(bId);
+            mElements.add(BookmarkListEntry.createBookmarkEntry(item));
         }
         notifyDataSetChanged();
     }
@@ -156,16 +142,8 @@
     // DragReorderableListAdapter implementation.
     @Override
     public @ViewType int getItemViewType(int position) {
-        if (position == 0 && hasPromoHeader()) {
-            return mPromoHeaderType;
-        } else {
-            BookmarkItem item = getItemByPosition(position);
-            if (item.isFolder()) {
-                return ViewType.FOLDER;
-            } else {
-                return ViewType.BOOKMARK;
-            }
-        }
+        BookmarkListEntry entry = getItemByPosition(position);
+        return entry.getViewType();
     }
 
     private ViewHolder createViewHolderHelper(ViewGroup parent, @LayoutRes int layoutId) {
@@ -342,7 +320,9 @@
     void moveUpOne(BookmarkId bookmarkId) {
         int pos = getPositionForBookmark(bookmarkId);
         mElements.remove(pos);
-        mElements.add(pos - 1, mDelegate.getModel().getBookmarkById(bookmarkId));
+        mElements.add(pos - 1,
+                BookmarkListEntry.createBookmarkEntry(
+                        mDelegate.getModel().getBookmarkById(bookmarkId)));
         setOrder(mElements);
     }
 
@@ -352,7 +332,9 @@
     void moveDownOne(BookmarkId bookmarkId) {
         int pos = getPositionForBookmark(bookmarkId);
         mElements.remove(pos);
-        mElements.add(pos + 1, mDelegate.getModel().getBookmarkById(bookmarkId));
+        mElements.add(pos + 1,
+                BookmarkListEntry.createBookmarkEntry(
+                        mDelegate.getModel().getBookmarkById(bookmarkId)));
         setOrder(mElements);
     }
 
@@ -386,11 +368,11 @@
         if (currentUIState == BookmarkUIState.STATE_LOADING) {
             return;
         } else if (currentUIState == BookmarkUIState.STATE_SEARCHING) {
-            mPromoHeaderType = ViewType.INVALID_PROMO;
+            mPromoHeaderType = ViewType.INVALID;
         } else {
             switch (mPromoHeaderManager.getPromoState()) {
                 case BookmarkPromoHeader.PromoState.PROMO_NONE:
-                    mPromoHeaderType = ViewType.INVALID_PROMO;
+                    mPromoHeaderType = ViewType.INVALID;
                     break;
                 case BookmarkPromoHeader.PromoState.PROMO_SIGNIN_PERSONALIZED:
                     mPromoHeaderType = ViewType.PERSONALIZED_SIGNIN_PROMO;
@@ -410,7 +392,7 @@
 
         if (!wasShowingPromo && willShowPromo) {
             // A null element at the 0th index represents a promo header.
-            mElements.add(0, null);
+            mElements.add(0, BookmarkListEntry.createSyncPromoHeader(mPromoHeaderType));
             if (shouldNotify) notifyItemInserted(0);
         } else if (wasShowingPromo && willShowPromo) {
             if (shouldNotify) notifyItemChanged(0);
@@ -464,7 +446,7 @@
     }
 
     @Override
-    protected void setOrder(List<BookmarkItem> bookmarkItems) {
+    protected void setOrder(List<BookmarkListEntry> listEntries) {
         assert !topLevelFoldersShowing() : "Cannot reorder top-level folders!";
         assert mCurrentFolder.getType()
                 != BookmarkType.PARTNER : "Cannot reorder partner bookmarks!";
@@ -477,7 +459,9 @@
         // Get the new order for the IDs.
         long[] newOrder = new long[endIndex - startIndex + 1];
         for (int i = startIndex; i <= endIndex; i++) {
-            newOrder[i - startIndex] = bookmarkItems.get(i).getId().getId();
+            BookmarkItem bookmarkItem = listEntries.get(i).getBookmarkItem();
+            assert bookmarkItem != null;
+            newOrder[i - startIndex] = bookmarkItem.getId().getId();
         }
         mDelegate.getModel().reorderBookmarks(mCurrentFolder, newOrder);
         if (mDragStateDelegate.getDragActive()) {
@@ -491,14 +475,17 @@
 
     private int getBookmarkItemEndIndex() {
         int endIndex = mElements.size() - 1;
-        if (!mElements.get(endIndex).isMovable()) {
+        BookmarkItem bookmarkItem = mElements.get(endIndex).getBookmarkItem();
+        assert bookmarkItem != null;
+        if (!bookmarkItem.isMovable()) {
             endIndex--;
         }
         return endIndex;
     }
 
-    private boolean isOrderable(BookmarkItem bItem) {
-        return bItem != null && bItem.isMovable();
+    private boolean isOrderable(BookmarkListEntry entry) {
+        return entry != null && entry.getBookmarkItem() != null
+                && entry.getBookmarkItem().isMovable();
     }
 
     @Override
@@ -511,19 +498,18 @@
     @Override
     @VisibleForTesting
     public boolean isPassivelyDraggable(ViewHolder viewHolder) {
-        BookmarkItem bItem = getItemByHolder(viewHolder);
-        return isOrderable(bItem);
+        return isOrderable(getItemByHolder(viewHolder));
     }
 
     @VisibleForTesting
     BookmarkId getIdByPosition(int position) {
-        BookmarkItem bItem = getItemByPosition(position);
-        if (bItem == null) return null;
-        return bItem.getId();
+        BookmarkListEntry entry = getItemByPosition(position);
+        if (entry == null || entry.getBookmarkItem() == null) return null;
+        return entry.getBookmarkItem().getId();
     }
 
     private boolean hasPromoHeader() {
-        return mPromoHeaderType != ViewType.INVALID_PROMO;
+        return mPromoHeaderType != ViewType.INVALID;
     }
 
     private @Location int getLocationFromPosition(int position) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkListEntry.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkListEntry.java
new file mode 100644
index 0000000..74ce7365c
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkListEntry.java
@@ -0,0 +1,79 @@
+// 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.bookmarks;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
+
+import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Represents different type of views in the bookmark UI.
+ */
+final class BookmarkListEntry {
+    /**
+     * Specifies the view types that the bookmark delegate screen can contain.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({ViewType.INVALID, ViewType.PERSONALIZED_SIGNIN_PROMO, ViewType.PERSONALIZED_SYNC_PROMO,
+            ViewType.SYNC_PROMO, ViewType.FOLDER, ViewType.BOOKMARK})
+    @interface ViewType {
+        int INVALID = -1;
+        int PERSONALIZED_SIGNIN_PROMO = 0;
+        int PERSONALIZED_SYNC_PROMO = 1;
+        int SYNC_PROMO = 2;
+        int FOLDER = 3;
+        int BOOKMARK = 4;
+    }
+
+    private final @ViewType int mViewType;
+    @Nullable
+    private final BookmarkItem mBookmarkItem;
+
+    private BookmarkListEntry(int viewType, @Nullable BookmarkItem bookmarkItem) {
+        this.mViewType = viewType;
+        this.mBookmarkItem = bookmarkItem;
+    }
+
+    /**
+     * Create an entry presenting a bookmark folder or bookmark.
+     * @param bookmarkItem The data object created from the bookmark backend.
+     */
+    static BookmarkListEntry createBookmarkEntry(@Nonnull BookmarkItem bookmarkItem) {
+        return new BookmarkListEntry(
+                bookmarkItem.isFolder() ? ViewType.FOLDER : ViewType.BOOKMARK, bookmarkItem);
+    }
+
+    /**
+     * Create an entry presenting a sync promo header.
+     * @param viewType The view type of the sync promo header.
+     */
+    static BookmarkListEntry createSyncPromoHeader(@ViewType int viewType) {
+        assert viewType == ViewType.PERSONALIZED_SIGNIN_PROMO
+                || viewType == ViewType.PERSONALIZED_SYNC_PROMO || viewType == ViewType.SYNC_PROMO;
+        return new BookmarkListEntry(viewType, /*bookmarkItem=*/null);
+    }
+
+    /**
+     * Returns the view type used in the bookmark list UI.
+     */
+    @ViewType
+    int getViewType() {
+        return mViewType;
+    }
+
+    /**
+     * Returns the view type used in the bookmark list UI. Can be null for non bookmark view types.
+     */
+    @Nullable
+    BookmarkItem getBookmarkItem() {
+        return mBookmarkItem;
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoUtils.java
index bb8ea3c..347b0ab1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoUtils.java
@@ -9,6 +9,7 @@
 
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
@@ -45,7 +46,7 @@
     // Suffix for PROMO_IS_DISMISSED and PROMO_TIMES_SEEN Chrome preference keys.
     public static final String ENHANCED_PROTECTION_PROMO_CARD_FEATURE =
             "EnhancedProtectionPromoCard";
-    private static final int MAX_IMPRESSION_SEEN = 10;
+    private static final int DEFAULT_MAX_IMPRESSION_SEEN = 22;
 
     // Do not instantiate.
     private EnhancedProtectionPromoUtils() {}
@@ -58,10 +59,13 @@
     static boolean shouldCreatePromo(@Nullable Profile profile) {
         String timesSeenKey = getTimesSeenKey();
         int timesSeen = SharedPreferencesManager.getInstance().readInt(timesSeenKey, 0);
+        int maxImpressions = ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
+                ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD,
+                "MaxEnhancedProtectionPromoImpressions", DEFAULT_MAX_IMPRESSION_SEEN);
         // TODO(bdea): If the user has pressed "Continue" and not selected Enhanced Protection,
         // should we still show the promo.
         return (profile != null) && !UserPrefs.get(profile).getBoolean(Pref.SAFE_BROWSING_ENHANCED)
-                && !isPromoDismissedInSharedPreference() && (timesSeen <= MAX_IMPRESSION_SEEN)
+                && !isPromoDismissedInSharedPreference() && (timesSeen <= maxImpressions)
                 && !SafeBrowsingBridge.isSafeBrowsingManaged();
     }
 
@@ -88,7 +92,9 @@
                 action, EnhancedProtectionPromoAction.TOTAL);
 
         if (action == EnhancedProtectionPromoAction.CREATED) return;
-
+        int maxImpressions = ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
+                ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD,
+                "MaxEnhancedProtectionPromoImpressions", DEFAULT_MAX_IMPRESSION_SEEN);
         String timesSeenKey = getTimesSeenKey();
         int timesSeen = SharedPreferencesManager.getInstance().readInt(timesSeenKey, 0);
         if (action == EnhancedProtectionPromoAction.SEEN) {
@@ -97,12 +103,12 @@
             RecordUserAction.record("NewTabPage.Promo.EnhancedProtectionPromo.Accepted");
             RecordHistogram.recordLinearCountHistogram(
                     "NewTabPage.Promo.EnhancedProtectionPromo.ImpressionUntilAction", timesSeen, 1,
-                    MAX_IMPRESSION_SEEN, MAX_IMPRESSION_SEEN + 1);
+                    maxImpressions, maxImpressions + 1);
         } else if (action == EnhancedProtectionPromoAction.DISMISSED) {
             RecordUserAction.record("NewTabPage.Promo.EnhancedProtectionPromo.Dismissed");
             RecordHistogram.recordLinearCountHistogram(
                     "NewTabPage.Promo.EnhancedProtectionPromo.ImpressionUntilDismissal", timesSeen,
-                    1, MAX_IMPRESSION_SEEN, MAX_IMPRESSION_SEEN + 1);
+                    1, maxImpressions, maxImpressions + 1);
         }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java
index c25765e..dbdd9ee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java
@@ -76,8 +76,8 @@
                 return getSigninPromoImpressionsCountBookmarks() < MAX_IMPRESSIONS_BOOKMARKS;
             case SigninAccessPoint.NTP_CONTENT_SUGGESTIONS:
                 int maxImpressions = ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
-                        ChromeFeatureList.SIGNIN_PROMO_MAX_IMPRESSIONS_ANDROID, "MaxImpressions",
-                        Integer.MAX_VALUE);
+                        ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD,
+                        "MaxSigninPromoImpressions", Integer.MAX_VALUE);
                 return SharedPreferencesManager.getInstance().readInt(
                                ChromePreferenceKeys.SIGNIN_PROMO_IMPRESSIONS_COUNT_NTP)
                         < maxImpressions;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/SwitchToTabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/SwitchToTabTest.java
index 9eba6648..4d09a26 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/SwitchToTabTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/SwitchToTabTest.java
@@ -6,6 +6,7 @@
 
 import static org.chromium.chrome.browser.multiwindow.MultiWindowTestHelper.moveActivityToFront;
 import static org.chromium.chrome.browser.multiwindow.MultiWindowTestHelper.waitForSecondChromeTabbedActivity;
+import static org.chromium.content_public.browser.test.util.CriteriaHelper.DEFAULT_POLLING_INTERVAL;
 
 import android.app.Activity;
 import android.app.Instrumentation;
@@ -31,7 +32,6 @@
 import org.chromium.base.ActivityState;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
@@ -71,6 +71,7 @@
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
     private static final int INVALID_INDEX = -1;
+    private static final long SEARCH_ACTIVITY_MAX_TIME_TO_POLL = 10000L;
 
     private EmbeddedTestServer mTestServer;
 
@@ -133,7 +134,7 @@
             } catch (InterruptedException e) {
                 throw new CriteriaNotSatisfiedException(e);
             }
-        });
+        }, SEARCH_ACTIVITY_MAX_TIME_TO_POLL, DEFAULT_POLLING_INTERVAL);
     }
 
     /**
@@ -243,7 +244,7 @@
         Intent intent = new Intent();
         SearchWidgetProvider.startSearchActivity(intent, /* isVoiceSearch = */ false);
         Activity searchActivity = instrumentation.waitForMonitorWithTimeout(
-                searchMonitor, CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL);
+                searchMonitor, SEARCH_ACTIVITY_MAX_TIME_TO_POLL);
         Assert.assertNotNull("Activity didn't start", searchActivity);
         Assert.assertTrue("Wrong activity started", searchActivity instanceof SearchActivity);
         instrumentation.removeMonitor(searchMonitor);
@@ -348,7 +349,6 @@
 
     @Test
     @MediumTest
-    @DisabledTest(message = "Flaky - https://crbug.com/1114938")
     @EnableFeatures("OmniboxTabSwitchSuggestions")
     public void testSwitchToTabInSearchActivity() throws InterruptedException {
         mTestServer = EmbeddedTestServer.createAndStartHTTPSServer(
@@ -370,7 +370,7 @@
             // Make sure chrome fully in background.
             Criteria.checkThat(tab.getWindowAndroid().getActivityState(),
                     Matchers.isOneOf(ActivityState.STOPPED, ActivityState.DESTROYED));
-        });
+        }, SEARCH_ACTIVITY_MAX_TIME_TO_POLL, DEFAULT_POLLING_INTERVAL);
 
         final LocationBarLayout locationBarLayout =
                 (LocationBarLayout) searchActivity.findViewById(R.id.search_location_bar);
@@ -385,6 +385,6 @@
             Criteria.checkThat(
                     tab.getWindowAndroid().getActivityState(), Matchers.is(ActivityState.RESUMED));
             Assert.assertEquals(tab, aboutTab);
-        });
+        }, SEARCH_ACTIVITY_MAX_TIME_TO_POLL, DEFAULT_POLLING_INTERVAL);
     }
 }
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 708a905..85f4002 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-88.0.4288.0_rc-r1-merged.afdo.bz2
+chromeos-chrome-amd64-88.0.4290.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/app/global_media_controls_strings.grdp b/chrome/app/global_media_controls_strings.grdp
index dd8c8a30..e601c311 100644
--- a/chrome/app/global_media_controls_strings.grdp
+++ b/chrome/app/global_media_controls_strings.grdp
@@ -15,5 +15,8 @@
   </message>
   <message name="IDS_GLOBAL_MEDIA_CONTROLS_STOP_CASTING_BUTTON_LABEL" desc="Label for a button that stops the current cast session.">
    Stop casting
+ </message>
+  <message name="IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION" desc="Label for the toggle that enables the Live Caption feature. Live Caption only works for English captions.">
+   Live Caption (English only)
   </message>
 </grit-part>
diff --git a/chrome/app/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION.png.sha1 b/chrome/app/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION.png.sha1
new file mode 100644
index 0000000..117eb47
--- /dev/null
+++ b/chrome/app/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION.png.sha1
@@ -0,0 +1 @@
+41b4f4aa6df1fecc6b9632615aeecf08260130c4
\ No newline at end of file
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn
index a86330a..1deb8a6 100644
--- a/chrome/app/vector_icons/BUILD.gn
+++ b/chrome/app/vector_icons/BUILD.gn
@@ -65,6 +65,7 @@
     "keyboard_arrow_right.icon",
     "keyboard_arrow_up.icon",
     "laptop.icon",
+    "live_caption.icon",
     "media_toolbar_button.icon",
     "media_toolbar_button_touch.icon",
     "mixed_content.icon",
diff --git a/chrome/app/vector_icons/live_caption.icon b/chrome/app/vector_icons/live_caption.icon
new file mode 100644
index 0000000..e74d9ed64
--- /dev/null
+++ b/chrome/app/vector_icons/live_caption.icon
@@ -0,0 +1,45 @@
+// 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.
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2, 5,
+CUBIC_TO, 2, 4.45f, 2.45f, 4, 3, 4,
+H_LINE_TO, 17,
+CUBIC_TO, 17.55f, 4, 18, 4.45f, 18, 5,
+V_LINE_TO, 15,
+CUBIC_TO, 18, 15.55f, 17.55f, 16, 17, 16,
+H_LINE_TO, 3,
+CUBIC_TO, 2.45f, 16, 2, 15.55f, 2, 15,
+V_LINE_TO, 5,
+CLOSE,
+MOVE_TO, 4, 6,
+H_LINE_TO, 16,
+V_LINE_TO, 14,
+H_LINE_TO, 4,
+V_LINE_TO, 6,
+CLOSE,
+MOVE_TO, 5, 8,
+H_LINE_TO, 7,
+V_LINE_TO, 10,
+H_LINE_TO, 5,
+V_LINE_TO, 8,
+CLOSE,
+MOVE_TO, 13, 11,
+H_LINE_TO, 15,
+V_LINE_TO, 13,
+H_LINE_TO, 13,
+V_LINE_TO, 11,
+CLOSE,
+MOVE_TO, 15, 8,
+H_LINE_TO, 8,
+V_LINE_TO, 10,
+H_LINE_TO, 15,
+V_LINE_TO, 8,
+CLOSE,
+MOVE_TO, 5, 11,
+H_LINE_TO, 12,
+V_LINE_TO, 13,
+H_LINE_TO, 5,
+V_LINE_TO, 11,
+CLOSE
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index d6d9386d..31c36e6 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -6075,7 +6075,10 @@
 
     if (is_android) {
       if (enable_arcore) {
-        deps += [ "//device/vr/android/arcore" ]
+        deps += [
+          "//components/webxr/android",
+          "//device/vr/android/arcore",
+        ]
       }
     } else {
       deps += [ "//device/vr/public/mojom" ]
diff --git a/chrome/browser/android/vr/BUILD.gn b/chrome/browser/android/vr/BUILD.gn
index 3fb5f2e..7b47d63 100644
--- a/chrome/browser/android/vr/BUILD.gn
+++ b/chrome/browser/android/vr/BUILD.gn
@@ -16,8 +16,6 @@
   sources = [
     "android_ui_gesture_target.cc",
     "android_ui_gesture_target.h",
-    "android_vr_utils.cc",
-    "android_vr_utils.h",
     "android_vsync_helper.cc",
     "android_vsync_helper.h",
     "autocomplete_controller.cc",
@@ -70,8 +68,6 @@
       "arcore_device/arcore_device_utils.cc",
       "arcore_device/arcore_java_utils.cc",
       "arcore_device/arcore_java_utils.h",
-      "chrome_arcore_install_helper.cc",
-      "chrome_arcore_install_helper.h",
     ]
   }
 
@@ -94,6 +90,7 @@
     "//components/search_engines:search_engines",
     "//components/webxr:webxr",
     "//components/webxr/android",
+    "//components/webxr/android:android_utils",
     "//content/public/browser",
     "//content/public/common",
     "//device/vr",
diff --git a/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc b/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc
index 2be0e368..126e3da 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc
@@ -8,8 +8,8 @@
 #include <utility>
 
 #include "base/android/jni_string.h"
-#include "chrome/browser/android/vr/android_vr_utils.h"
 #include "chrome/browser/android/vr/ar_jni_headers/ArCoreJavaUtils_jni.h"
+#include "components/webxr/android/webxr_utils.h"
 #include "device/vr/android/arcore/arcore_shim.h"
 
 using base::android::AttachCurrentThread;
@@ -49,7 +49,8 @@
 
   Java_ArCoreJavaUtils_startSession(
       env, j_arcore_java_utils_,
-      GetJavaWebContents(render_process_id, render_frame_id), use_overlay);
+      webxr::GetJavaWebContents(render_process_id, render_frame_id),
+      use_overlay);
 }
 
 void ArCoreJavaUtils::EndSession() {
diff --git a/chrome/browser/android/vr/chrome_arcore_install_helper.cc b/chrome/browser/android/vr/chrome_arcore_install_helper.cc
deleted file mode 100644
index 711467d..0000000
--- a/chrome/browser/android/vr/chrome_arcore_install_helper.cc
+++ /dev/null
@@ -1,29 +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.
-
-#include "chrome/browser/android/vr/chrome_arcore_install_helper.h"
-
-#include "chrome/browser/android/vr/android_vr_utils.h"
-#include "chrome/browser/infobars/infobar_service.h"
-#include "components/webxr/android/arcore_install_helper.h"
-
-using base::android::AttachCurrentThread;
-
-namespace vr {
-ChromeArCoreInstallHelper::ChromeArCoreInstallHelper() = default;
-ChromeArCoreInstallHelper::~ChromeArCoreInstallHelper() = default;
-
-void ChromeArCoreInstallHelper::EnsureInstalled(
-    int render_process_id,
-    int render_frame_id,
-    base::OnceCallback<void(bool)> install_callback) {
-  auto* infobar_manager = InfoBarService::FromWebContents(
-      GetWebContents(render_process_id, render_frame_id));
-  DCHECK(infobar_manager);
-  arcore_install_helper_.EnsureInstalled(render_process_id, render_frame_id,
-                                         infobar_manager,
-                                         std::move(install_callback));
-}
-
-}  // namespace vr
diff --git a/chrome/browser/android/vr/chrome_arcore_install_helper.h b/chrome/browser/android/vr/chrome_arcore_install_helper.h
deleted file mode 100644
index 4e95f73..0000000
--- a/chrome/browser/android/vr/chrome_arcore_install_helper.h
+++ /dev/null
@@ -1,37 +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.
-
-#ifndef CHROME_BROWSER_ANDROID_VR_CHROME_ARCORE_INSTALL_HELPER_H_
-#define CHROME_BROWSER_ANDROID_VR_CHROME_ARCORE_INSTALL_HELPER_H_
-
-#include "base/callback.h"
-#include "chrome/browser/vr/vr_export.h"
-#include "components/webxr/android/arcore_install_helper.h"
-#include "content/public/browser/xr_install_helper.h"
-
-namespace vr {
-
-// The Actual ArCoreInstallHelper needs an InfoBarManager interface, which
-// content/browser is unable to provide, as it has no means of accessing the
-// embedder specific factory method, to that end we make a small wrapper class
-// to extract the relevant InfoBarManager.
-class VR_EXPORT ChromeArCoreInstallHelper : public content::XrInstallHelper {
- public:
-  ChromeArCoreInstallHelper();
-  ~ChromeArCoreInstallHelper() override;
-  ChromeArCoreInstallHelper(const ChromeArCoreInstallHelper&) = delete;
-  ChromeArCoreInstallHelper& operator=(const ChromeArCoreInstallHelper&) =
-      delete;
-  void EnsureInstalled(
-      int render_process_id,
-      int render_frame_id,
-      base::OnceCallback<void(bool)> install_callback) override;
-
- private:
-  webxr::ArCoreInstallHelper arcore_install_helper_;
-};
-
-}  // namespace vr
-
-#endif  // CHROME_BROWSER_ANDROID_VR_CHROME_ARCORE_INSTALL_HELPER_H_
diff --git a/chrome/browser/android/vr/gvr_scheduler_delegate.cc b/chrome/browser/android/vr/gvr_scheduler_delegate.cc
index a7ed985e..e82bb87 100644
--- a/chrome/browser/android/vr/gvr_scheduler_delegate.cc
+++ b/chrome/browser/android/vr/gvr_scheduler_delegate.cc
@@ -216,9 +216,6 @@
   auto* config = session->device_config.get();
 
   config->supports_viewport_scaling = true;
-  session->enviroment_blend_mode =
-      device::mojom::XREnvironmentBlendMode::kOpaque;
-  session->interaction_mode = device::mojom::XRInteractionMode::kScreenSpace;
 
   // This scalar will be applied in the renderer to the recommended render
   // target sizes. For WebVR it will always be applied, for WebXR it can be
diff --git a/chrome/browser/android/vr/vrcore_install_helper.cc b/chrome/browser/android/vr/vrcore_install_helper.cc
index 76ac24d..f054811 100644
--- a/chrome/browser/android/vr/vrcore_install_helper.cc
+++ b/chrome/browser/android/vr/vrcore_install_helper.cc
@@ -9,8 +9,8 @@
 
 #include "base/bind.h"
 #include "chrome/android/features/vr/jni_headers/VrCoreInstallUtils_jni.h"
-#include "chrome/browser/android/vr/android_vr_utils.h"
 #include "chrome/browser/android/vr/vr_module_provider.h"
+#include "components/webxr/android/webxr_utils.h"
 
 using base::android::AttachCurrentThread;
 
@@ -65,7 +65,7 @@
     // When completed, java will call: OnInstallResult
     Java_VrCoreInstallUtils_requestInstallVrCore(
         env, java_install_utils_,
-        GetJavaWebContents(render_process_id, render_frame_id));
+        webxr::GetJavaWebContents(render_process_id, render_frame_id));
     return;
   }
 
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 7a0a164b..480865c 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -351,7 +351,6 @@
 #include "third_party/blink/public/common/loader/referrer_utils.h"
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
 #include "third_party/blink/public/common/switches.h"
-#include "third_party/blink/public/common/web_preferences/autoplay_policy.h"
 #include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom.h"
 #include "third_party/blink/public/mojom/user_agent/user_agent_metadata.mojom.h"
@@ -3449,18 +3448,18 @@
     // If autoplay is allowed by policy then force the no user gesture required
     // autoplay policy.
     web_prefs->autoplay_policy =
-        blink::web_pref::AutoplayPolicy::kNoUserGestureRequired;
+        blink::mojom::AutoplayPolicy::kNoUserGestureRequired;
   } else if (base::FeatureList::IsEnabled(media::kAutoplayDisableSettings) &&
              web_prefs->autoplay_policy ==
-                 blink::web_pref::AutoplayPolicy::
+                 blink::mojom::AutoplayPolicy::
                      kDocumentUserActivationRequired) {
     // If the autoplay disable settings feature is enabled and the autoplay
     // policy is set to using the unified policy then set the default autoplay
     // policy based on user preference.
     web_prefs->autoplay_policy =
         UnifiedAutoplayConfig::ShouldBlockAutoplay(profile)
-            ? blink::web_pref::AutoplayPolicy::kDocumentUserActivationRequired
-            : blink::web_pref::AutoplayPolicy::kNoUserGestureRequired;
+            ? blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired
+            : blink::mojom::AutoplayPolicy::kNoUserGestureRequired;
   }
 
   auto* native_theme = GetWebTheme();
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 660fc2d..f9f9671a 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -3612,7 +3612,6 @@
     "power/ml/recent_events_counter_unittest.cc",
     "power/ml/smart_dim/ml_agent_unittest.cc",
     "power/ml/smart_dim/ml_agent_util_unittest.cc",
-    "power/ml/smart_dim/model_unittest.cc",
     "power/ml/user_activity_manager_unittest.cc",
     "power/ml/user_activity_ukm_logger_helpers_unittest.cc",
     "power/ml/user_activity_ukm_logger_unittest.cc",
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc
index 3f735624..ec6e092 100644
--- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc
@@ -18,19 +18,13 @@
 using AXStringProperty = mojom::AccessibilityStringProperty;
 
 base::Optional<ax::mojom::Event> FromContentChangeTypesToAXEvent(
-    const std::vector<int32_t>& arc_content_change_types,
-    const AccessibilityInfoDataWrapper& source_node) {
-  if (!base::Contains(
+    const std::vector<int32_t>& arc_content_change_types) {
+  if (base::Contains(
           arc_content_change_types,
           static_cast<int32_t>(mojom::ContentChangeType::STATE_DESCRIPTION))) {
-    return base::nullopt;
-  }
-  const AXNodeInfoData* node_ptr = source_node.GetNode();
-  if (node_ptr && node_ptr->range_info) {
-    return ax::mojom::Event::kValueChanged;
-  } else {
     return ax::mojom::Event::kAriaAttributeChanged;
   }
+  return base::nullopt;
 }
 
 ax::mojom::Event ToAXEvent(
@@ -52,8 +46,7 @@
     case mojom::AccessibilityEventType::WINDOW_STATE_CHANGED: {
       if (source_node && arc_content_change_types.has_value()) {
         const base::Optional<ax::mojom::Event> event_or_null =
-            FromContentChangeTypesToAXEvent(arc_content_change_types.value(),
-                                            *source_node);
+            FromContentChangeTypesToAXEvent(arc_content_change_types.value());
         if (event_or_null.has_value()) {
           return event_or_null.value();
         }
@@ -68,8 +61,7 @@
     case mojom::AccessibilityEventType::WINDOW_CONTENT_CHANGED:
       if (source_node && arc_content_change_types.has_value()) {
         const base::Optional<ax::mojom::Event> event_or_null =
-            FromContentChangeTypesToAXEvent(arc_content_change_types.value(),
-                                            *source_node);
+            FromContentChangeTypesToAXEvent(arc_content_change_types.value());
         if (event_or_null.has_value()) {
           return event_or_null.value();
         }
@@ -92,7 +84,7 @@
       // See the comment on AXTreeSourceArc::NotifyAccessibilityEvent.
       if (source_node && source_node->IsNode() &&
           source_node->GetNode()->range_info) {
-        return ax::mojom::Event::kValueChanged;
+        return ax::mojom::Event::kAriaAttributeChanged;
       } else {
         return ax::mojom::Event::kFocus;
       }
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h
index 168baf8..be2c5bc 100644
--- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h
@@ -21,8 +21,7 @@
 // This function is only called when EventType is WINDOW_STATE_CHANGED or
 // WINDOW_CONTENT_CHANGED.
 base::Optional<ax::mojom::Event> FromContentChangeTypesToAXEvent(
-    const std::vector<int>& arc_content_change_types,
-    const AccessibilityInfoDataWrapper& source_node);
+    const std::vector<int>& arc_content_change_types);
 
 ax::mojom::Event ToAXEvent(
     mojom::AccessibilityEventType arc_event_type,
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util_unittest.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util_unittest.cc
index 1f96b75a..02ee263 100644
--- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util_unittest.cc
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util_unittest.cc
@@ -18,81 +18,46 @@
 using AXRangeInfoData = mojom::AccessibilityRangeInfoData;
 
 TEST(ArcAccessibilityUtilTest, FromContentChangeTypesToAXEvent) {
-  auto range_widget = AXNodeInfoData::New();
-  range_widget->range_info = AXRangeInfoData::New();
-  AccessibilityNodeInfoDataWrapper source_node_range(nullptr,
-                                                     range_widget.get());
-  auto not_range_widget = AXNodeInfoData::New();
-  AccessibilityNodeInfoDataWrapper source_node_not_range(
-      nullptr, not_range_widget.get());
+  auto node_info_data = AXNodeInfoData::New();
+  AccessibilityNodeInfoDataWrapper source_node_info_wrapper(
+      nullptr, node_info_data.get());
 
   std::vector<int32_t> empty_list = {};
-  EXPECT_EQ(base::nullopt,
-            FromContentChangeTypesToAXEvent(empty_list, source_node_range));
-  EXPECT_EQ(base::nullopt,
-            FromContentChangeTypesToAXEvent(empty_list, source_node_not_range));
+  EXPECT_EQ(base::nullopt, FromContentChangeTypesToAXEvent(empty_list));
 
   std::vector<int32_t> state_description = {
       static_cast<int32_t>(mojom::ContentChangeType::STATE_DESCRIPTION)};
-  EXPECT_EQ(
-      ax::mojom::Event::kValueChanged,
-      FromContentChangeTypesToAXEvent(state_description, source_node_range));
   EXPECT_EQ(ax::mojom::Event::kAriaAttributeChanged,
-            FromContentChangeTypesToAXEvent(state_description,
-                                            source_node_not_range));
+            FromContentChangeTypesToAXEvent(state_description));
 
-  EXPECT_EQ(ax::mojom::Event::kValueChanged,
-            ToAXEvent(AXEventType::WINDOW_STATE_CHANGED, state_description,
-                      &source_node_range, &source_node_range));
-  EXPECT_EQ(ax::mojom::Event::kValueChanged,
-            ToAXEvent(AXEventType::WINDOW_CONTENT_CHANGED, state_description,
-                      &source_node_range, &source_node_range));
   EXPECT_EQ(ax::mojom::Event::kAriaAttributeChanged,
             ToAXEvent(AXEventType::WINDOW_STATE_CHANGED, state_description,
-                      &source_node_not_range, &source_node_not_range));
+                      &source_node_info_wrapper, &source_node_info_wrapper));
   EXPECT_EQ(ax::mojom::Event::kAriaAttributeChanged,
             ToAXEvent(AXEventType::WINDOW_CONTENT_CHANGED, state_description,
-                      &source_node_not_range, &source_node_not_range));
+                      &source_node_info_wrapper, &source_node_info_wrapper));
 
   std::vector<int32_t> without_state_description = {
       static_cast<int32_t>(mojom::ContentChangeType::TEXT)};
-  EXPECT_EQ(base::nullopt, FromContentChangeTypesToAXEvent(
-                               without_state_description, source_node_range));
   EXPECT_EQ(base::nullopt,
-            FromContentChangeTypesToAXEvent(without_state_description,
-                                            source_node_not_range));
+            FromContentChangeTypesToAXEvent(without_state_description));
 
   std::vector<int32_t> include_state_description = {
       static_cast<int32_t>(mojom::ContentChangeType::TEXT),
       static_cast<int32_t>(mojom::ContentChangeType::STATE_DESCRIPTION)};
-  EXPECT_EQ(ax::mojom::Event::kValueChanged,
-            FromContentChangeTypesToAXEvent(include_state_description,
-                                            source_node_range));
   EXPECT_EQ(ax::mojom::Event::kAriaAttributeChanged,
-            FromContentChangeTypesToAXEvent(include_state_description,
-                                            source_node_not_range));
+            FromContentChangeTypesToAXEvent(include_state_description));
 
   EXPECT_EQ(
-      ax::mojom::Event::kValueChanged,
-      ToAXEvent(AXEventType::WINDOW_STATE_CHANGED, include_state_description,
-                &source_node_range, &source_node_range));
-  EXPECT_EQ(
-      ax::mojom::Event::kValueChanged,
-      ToAXEvent(AXEventType::WINDOW_CONTENT_CHANGED, include_state_description,
-                &source_node_range, &source_node_range));
-  EXPECT_EQ(
       ax::mojom::Event::kAriaAttributeChanged,
       ToAXEvent(AXEventType::WINDOW_STATE_CHANGED, include_state_description,
-                &source_node_not_range, &source_node_not_range));
+                &source_node_info_wrapper, &source_node_info_wrapper));
   EXPECT_EQ(
       ax::mojom::Event::kAriaAttributeChanged,
       ToAXEvent(AXEventType::WINDOW_CONTENT_CHANGED, include_state_description,
-                &source_node_not_range, &source_node_not_range));
+                &source_node_info_wrapper, &source_node_info_wrapper));
 
   std::vector<int32_t> not_enum_value = {111};
-  EXPECT_EQ(base::nullopt,
-            FromContentChangeTypesToAXEvent(not_enum_value, source_node_range));
-  EXPECT_EQ(base::nullopt, FromContentChangeTypesToAXEvent(
-                               not_enum_value, source_node_not_range));
+  EXPECT_EQ(base::nullopt, FromContentChangeTypesToAXEvent(not_enum_value));
 }
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc
index 6c0b73e2..33d0ba77 100644
--- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc
+++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc
@@ -669,10 +669,11 @@
   SetProperty(item, AXBooleanProperty::IMPORTANCE, true);
   SetProperty(item, AXBooleanProperty::VISIBLE_TO_USER, true);
 
-  // A selected event from Slider is kValueChanged.
+  // A selected event from Slider is kAriaAttributeChanged.
   event->source_id = slider->id;
   CallNotifyAccessibilityEvent(event.get());
-  EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kValueChanged));
+  EXPECT_EQ(1,
+            GetDispatchedEventCount(ax::mojom::Event::kAriaAttributeChanged));
 
   // A selected event from a collection. In Android, these event properties are
   // populated by AdapterView.
@@ -1228,11 +1229,13 @@
   SetProperty(event.get(), AXEventIntListProperty::CONTENT_CHANGE_TYPES,
               content_change_types);
   CallNotifyAccessibilityEvent(event.get());
-  EXPECT_EQ(ax::mojom::Event::kValueChanged, last_dispatched_event_type());
+  EXPECT_EQ(ax::mojom::Event::kAriaAttributeChanged,
+            last_dispatched_event_type());
 
   event->event_type = AXEventType::WINDOW_CONTENT_CHANGED;
   CallNotifyAccessibilityEvent(event.get());
-  EXPECT_EQ(ax::mojom::Event::kValueChanged, last_dispatched_event_type());
+  EXPECT_EQ(ax::mojom::Event::kAriaAttributeChanged,
+            last_dispatched_event_type());
 
   // State description changed event from non range widget.
   event->node_data.push_back(AXNodeInfoData::New());
diff --git a/chrome/browser/chromeos/arc/auth/arc_active_directory_enrollment_token_fetcher.cc b/chrome/browser/chromeos/arc/auth/arc_active_directory_enrollment_token_fetcher.cc
index eb3e55a05..07a087e8 100644
--- a/chrome/browser/chromeos/arc/auth/arc_active_directory_enrollment_token_fetcher.cc
+++ b/chrome/browser/chromeos/arc/auth/arc_active_directory_enrollment_token_fetcher.cc
@@ -102,9 +102,9 @@
               ? url_loader_factory_for_testing()
               : g_browser_process->system_network_context_manager()
                     ->GetSharedURLLoaderFactory(),
-          base::Bind(&ArcActiveDirectoryEnrollmentTokenFetcher::
-                         OnEnrollmentTokenResponseReceived,
-                     weak_ptr_factory_.GetWeakPtr()));
+          base::BindOnce(&ArcActiveDirectoryEnrollmentTokenFetcher::
+                             OnEnrollmentTokenResponseReceived,
+                         weak_ptr_factory_.GetWeakPtr()));
 
   em::ActiveDirectoryEnrollPlayUserRequest* enroll_request =
       config->request()->mutable_active_directory_enroll_play_user_request();
diff --git a/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.cc b/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.cc
index fde3d5f..538640fb3 100644
--- a/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.cc
+++ b/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.cc
@@ -74,8 +74,8 @@
 void ArcBackgroundAuthCodeFetcher::Fetch(FetchCallback callback) {
   DCHECK(callback_.is_null());
   callback_ = std::move(callback);
-  context_.Prepare(base::Bind(&ArcBackgroundAuthCodeFetcher::OnPrepared,
-                              weak_ptr_factory_.GetWeakPtr()));
+  context_.Prepare(base::BindOnce(&ArcBackgroundAuthCodeFetcher::OnPrepared,
+                                  weak_ptr_factory_.GetWeakPtr()));
 }
 
 void ArcBackgroundAuthCodeFetcher::OnPrepared(bool success) {
diff --git a/chrome/browser/chromeos/arc/optin/arc_terms_of_service_default_negotiator_unittest.cc b/chrome/browser/chromeos/arc/optin/arc_terms_of_service_default_negotiator_unittest.cc
index 3ee9ede..a8c46d6 100644
--- a/chrome/browser/chromeos/arc/optin/arc_terms_of_service_default_negotiator_unittest.cc
+++ b/chrome/browser/chromeos/arc/optin/arc_terms_of_service_default_negotiator_unittest.cc
@@ -174,7 +174,7 @@
 
 ArcTermsOfServiceNegotiator::NegotiationCallback UpdateStatusCallback(
     Status* status) {
-  return base::Bind(
+  return base::BindOnce(
       [](Status* status, bool accepted) {
         *status = accepted ? Status::ACCEPTED : Status::CANCELLED;
       },
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 69f6ff6d..9bdb7e7 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -680,8 +680,7 @@
 
   arc_data_snapshotd_manager_ =
       std::make_unique<arc::data_snapshotd::ArcDataSnapshotdManager>(
-          g_browser_process->local_state(),
-          base::BindOnce(chrome::AttemptUserExit));
+          g_browser_process->local_state());
   if (base::FeatureList::IsEnabled(::features::kWilcoDtc))
     wilco_dtc_supportd_manager_ = std::make_unique<WilcoDtcSupportdManager>();
 
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 d89054d..f01825a 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -3638,7 +3638,7 @@
       auto* frame_header = ash::FrameHeader::Get(widget);
       window_info.caption_height = frame_header->GetHeaderHeight();
 
-      const chromeos::CaptionButtonModel* button_model =
+      const ash::CaptionButtonModel* button_model =
           frame_header->GetCaptionButtonModel();
       int caption_button_enabled_status = 0;
       int caption_button_visible_status = 0;
diff --git a/chrome/browser/chromeos/extensions/echo_private_api.cc b/chrome/browser/chromeos/extensions/echo_private_api.cc
index 2d3670b..2b9f4e2 100644
--- a/chrome/browser/chromeos/extensions/echo_private_api.cc
+++ b/chrome/browser/chromeos/extensions/echo_private_api.cc
@@ -25,6 +25,7 @@
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/common/extensions/api/echo_private.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
@@ -36,15 +37,6 @@
 
 namespace echo_api = extensions::api::echo_private;
 
-namespace {
-
-// URL of "More info" link shown in echo dialog in GetUserConsent function.
-const char kMoreInfoLink[] =
-    "chrome-extension://honijodknafkokifofgiaalefdiedpko/main.html?"
-    "answer=2677280";
-
-}  // namespace
-
 namespace chromeos {
 
 namespace echo_offer {
@@ -213,7 +205,7 @@
 
 void EchoPrivateGetUserConsentFunction::OnMoreInfoLinkClicked() {
   ChromeExtensionFunctionDetails details(this);
-  NavigateParams params(details.GetProfile(), GURL(kMoreInfoLink),
+  NavigateParams params(details.GetProfile(), GURL(chrome::kEchoLearnMoreURL),
                         ui::PAGE_TRANSITION_LINK);
   // Open the link in a new window. The echo dialog is modal, so the current
   // window is useless until the dialog is closed.
diff --git a/chrome/browser/chromeos/file_manager/devtools_listener.cc b/chrome/browser/chromeos/file_manager/devtools_listener.cc
index e702456..82d4e442 100644
--- a/chrome/browser/chromeos/file_manager/devtools_listener.cc
+++ b/chrome/browser/chromeos/file_manager/devtools_listener.cc
@@ -72,7 +72,7 @@
 }
 
 std::string DevToolsListener::HostString(content::DevToolsAgentHost* host,
-                                         const std::string& prefix) {
+                                         const std::string& prefix = "") {
   std::string result = base::StrCat(
       {prefix, " ", host->GetType(), " title: ", host->GetTitle()});
   std::string description = host->GetDescription();
diff --git a/chrome/browser/chromeos/file_manager/devtools_listener.h b/chrome/browser/chromeos/file_manager/devtools_listener.h
index b9f73c6..fc59da2 100644
--- a/chrome/browser/chromeos/file_manager/devtools_listener.h
+++ b/chrome/browser/chromeos/file_manager/devtools_listener.h
@@ -42,7 +42,7 @@
   // Returns a string that uniquely identifies a host
   // with an optional prefix.
   static std::string HostString(content::DevToolsAgentHost* host,
-                                const std::string& prefix = {});
+                                const std::string& prefix);
 
  private:
   // Enable CDP on host.
@@ -82,7 +82,7 @@
 
   base::OnceClosure value_closure_;
   std::unique_ptr<base::DictionaryValue> value_;
-  int value_id_;
+  int value_id_ = 0;
 
   const std::string uuid_;
   bool navigated_ = false;
diff --git a/chrome/browser/chromeos/file_manager/devtools_listener_browsertest.cc b/chrome/browser/chromeos/file_manager/devtools_listener_browsertest.cc
deleted file mode 100644
index 464199f..0000000
--- a/chrome/browser/chromeos/file_manager/devtools_listener_browsertest.cc
+++ /dev/null
@@ -1,115 +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.
-
-#include <map>
-#include <memory>
-
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/path_service.h"
-#include "base/process/process_handle.h"
-#include "base/threading/thread_restrictions.h"
-#include "chrome/browser/chromeos/file_manager/devtools_listener.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "content/public/browser/devtools_agent_host.h"
-#include "content/public/browser/devtools_agent_host_observer.h"
-#include "content/public/test/browser_test.h"
-#include "content/public/test/browser_test_utils.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace file_manager {
-
-class DevToolsListenerBrowserTest : public content::DevToolsAgentHostObserver,
-                                    public InProcessBrowserTest {
- public:
-  DevToolsListenerBrowserTest() = default;
-
-  void SetUpOnMainThread() override {
-    process_id_ = base::GetUniqueIdForProcess().GetUnsafeValue();
-    content::DevToolsAgentHost::AddObserver(this);
-
-    base::ScopedAllowBlockingForTesting allow_blocking;
-    CHECK(tmp_dir_.CreateUniqueTempDir());
-  }
-
-  bool ShouldForceDevToolsAgentHostCreation() override { return true; }
-
-  void DevToolsAgentHostCreated(content::DevToolsAgentHost* host) override {
-    CHECK(devtools_agent_.find(host) == devtools_agent_.end());
-    devtools_agent_[host].reset(new DevToolsListener(host, process_id_));
-  }
-
-  void DevToolsAgentHostAttached(content::DevToolsAgentHost* host) override {}
-
-  void DevToolsAgentHostNavigated(content::DevToolsAgentHost* host) override {
-    if (devtools_agent_.find(host) == devtools_agent_.end())
-      return;
-    devtools_agent_.find(host)->second->Navigated(host);
-  }
-
-  void DevToolsAgentHostDetached(content::DevToolsAgentHost* host) override {}
-
-  void DevToolsAgentHostCrashed(content::DevToolsAgentHost* host,
-                                base::TerminationStatus status) override {
-    if (devtools_agent_.find(host) == devtools_agent_.end())
-      return;
-    LOG(FATAL) << "Host crashed: " << DevToolsListener::HostString(host);
-  }
-
-  void CollectCodeCoverage() {
-    base::ScopedAllowBlockingForTesting allow_blocking;
-
-    base::FilePath coverage_store =
-        tmp_dir_.GetPath().AppendASCII("devtools_listener_browser_test");
-    CHECK(base::CreateDirectory(coverage_store));
-
-    for (auto& agent : devtools_agent_) {
-      auto* host = agent.first;
-      EXPECT_TRUE(agent.second->HasCoverage(host));
-      agent.second->GetCoverage(host, coverage_store, "fake_test_name");
-      agent.second->Detach(host);
-    }
-
-    ASSERT_FALSE(base::IsDirectoryEmpty(coverage_store));
-  }
-
- private:
-  base::ScopedTempDir tmp_dir_;
-  uint32_t process_id_ = 0;
-  std::map<content::DevToolsAgentHost*, std::unique_ptr<DevToolsListener>>
-      devtools_agent_;
-  base::FilePath coverage_store_;
-
-  DISALLOW_COPY_AND_ASSIGN(DevToolsListenerBrowserTest);
-};
-
-IN_PROC_BROWSER_TEST_F(DevToolsListenerBrowserTest, CanCollectCodeCoverage) {
-  base::FilePath test_data_dir;
-  base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
-  embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
-
-  ASSERT_TRUE(embedded_test_server()->Start());
-  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
-      browser(), embedded_test_server()->GetURL("/title2.html"), 1);
-
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  ASSERT_TRUE(
-      content::ExecJs(web_contents, "(function() { console.log('test'); })()"));
-
-  content::DevToolsAgentHost::RemoveObserver(this);
-  content::RunAllTasksUntilIdle();
-
-  CollectCodeCoverage();
-
-  content::DevToolsAgentHost::DetachAllClients();
-  content::RunAllTasksUntilIdle();
-}
-
-}  // namespace file_manager
diff --git a/chrome/browser/chromeos/file_manager/file_manager_string_util.cc b/chrome/browser/chromeos/file_manager/file_manager_string_util.cc
index f2636df825..594d8f7 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_string_util.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_string_util.cc
@@ -426,6 +426,7 @@
              IDS_FILE_BROWSER_ADD_NEW_SERVICES_BUTTON_LABEL);
   SET_STRING("ALL_FILES_FILTER", IDS_FILE_BROWSER_ALL_FILES_FILTER);
   SET_STRING("ARCHIVE_MOUNT_FAILED", IDS_FILE_BROWSER_ARCHIVE_MOUNT_FAILED);
+  SET_STRING("ARCHIVE_MOUNT_MESSAGE", IDS_FILE_BROWSER_ARCHIVE_MOUNT_MESSAGE);
   SET_STRING("CALCULATING_SIZE", IDS_FILE_BROWSER_CALCULATING_SIZE);
   SET_STRING("CAMERA_DIRECTORY_LABEL", IDS_FILE_BROWSER_CAMERA_DIRECTORY_LABEL);
   SET_STRING("CANCEL_ACTIVITY_LABEL", IDS_FILE_BROWSER_CANCEL_ACTIVITY_LABEL);
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc
index 822902fe..5b8d6b3 100644
--- a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc
+++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc
@@ -124,8 +124,7 @@
   } else {
     auto_enrollment_controller_->Start();
   }
-  network_portal_detector::GetInstance()->StartPortalDetection(
-      false /* force */);
+  network_portal_detector::GetInstance()->StartPortalDetection();
 }
 
 void AutoEnrollmentCheckScreen::HideImpl() {}
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 941d44f..e1ab31c3 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -94,7 +94,6 @@
 #include "chromeos/strings/grit/chromeos_strings.h"
 #include "components/account_id/account_id.h"
 #include "components/arc/arc_util.h"
-#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
 #include "components/google/core/common/google_util.h"
 #include "components/policy/core/common/cloud/cloud_policy_client.h"
 #include "components/policy/core/common/cloud/cloud_policy_core.h"
@@ -346,42 +345,6 @@
   return offline_signin_limit - (now - last_online_signin);
 }
 
-// Returns account ID of a public session account if it is unique, otherwise
-// returns invalid account ID.
-AccountId GetArcDataSnapshotAutoLoginAccountId(
-    const std::vector<policy::DeviceLocalAccount>& device_local_accounts) {
-  AccountId auto_login_account_id = EmptyAccountId();
-  for (std::vector<policy::DeviceLocalAccount>::const_iterator it =
-           device_local_accounts.begin();
-       it != device_local_accounts.end(); ++it) {
-    if (it->type == policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION) {
-      // Do not perform ARC data snapshot auto-login if more than one public
-      // session account is configured.
-      if (auto_login_account_id.is_valid())
-        return EmptyAccountId();
-      auto_login_account_id = AccountId::FromUserEmail(it->user_id);
-      VLOG(2) << "PublicSession autologin found: " << it->user_id;
-    }
-  }
-  return auto_login_account_id;
-}
-
-// Returns account ID if a corresponding to |auto_login_account_id| device local
-// account exists, otherwise returns invalid account ID.
-AccountId GetPublicSessionAutoLoginAccountId(
-    const std::vector<policy::DeviceLocalAccount>& device_local_accounts,
-    const std::string& auto_login_account_id) {
-  for (std::vector<policy::DeviceLocalAccount>::const_iterator it =
-           device_local_accounts.begin();
-       it != device_local_accounts.end(); ++it) {
-    if (it->account_id == auto_login_account_id) {
-      VLOG(2) << "PublicSession autologin found: " << it->user_id;
-      return AccountId::FromUserEmail(it->user_id);
-    }
-  }
-  return EmptyAccountId();
-}
-
 class AutoLaunchNotificationDelegate
     : public message_center::HandleNotificationClickDelegate {
  public:
@@ -1592,17 +1555,16 @@
       policy::GetDeviceLocalAccounts(cros_settings_);
   const bool show_update_required_screen = IsUpdateRequiredDeadlineReached();
 
-  auto* data_snapshotd_manager =
-      arc::data_snapshotd::ArcDataSnapshotdManager::Get();
-  bool is_arc_data_snapshot_autologin =
-      (data_snapshotd_manager &&
-       data_snapshotd_manager->IsAutoLoginConfigured());
-  if (is_arc_data_snapshot_autologin) {
-    public_session_auto_login_account_id_ =
-        GetArcDataSnapshotAutoLoginAccountId(device_local_accounts);
-  } else {
-    public_session_auto_login_account_id_ = GetPublicSessionAutoLoginAccountId(
-        device_local_accounts, auto_login_account_id);
+  public_session_auto_login_account_id_ = EmptyAccountId();
+  for (std::vector<policy::DeviceLocalAccount>::const_iterator it =
+           device_local_accounts.begin();
+       it != device_local_accounts.end(); ++it) {
+    if (it->account_id == auto_login_account_id) {
+      public_session_auto_login_account_id_ =
+          AccountId::FromUserEmail(it->user_id);
+      VLOG(2) << "PublicSession autologin found: " << it->user_id;
+      break;
+    }
   }
 
   const user_manager::User* public_session_user =
@@ -1614,8 +1576,7 @@
     public_session_auto_login_account_id_ = EmptyAccountId();
   }
 
-  if (is_arc_data_snapshot_autologin ||
-      !cros_settings_->GetInteger(kAccountsPrefDeviceLocalAccountAutoLoginDelay,
+  if (!cros_settings_->GetInteger(kAccountsPrefDeviceLocalAccountAutoLoginDelay,
                                   &auto_login_delay_)) {
     auto_login_delay_ = 0;
   }
@@ -1694,20 +1655,6 @@
     StopAutoLoginTimer();
   }
 
-  // Block auto-login flow until ArcDataSnapshotdManager is ready to enter an
-  // auto-login session.
-  // ArcDataSnapshotdManager stores a reset auto-login callback to fire it once
-  // it is ready.
-  auto* data_snapshotd_manager =
-      arc::data_snapshotd::ArcDataSnapshotdManager::Get();
-  if (data_snapshotd_manager && !data_snapshotd_manager->IsAutoLoginAllowed() &&
-      data_snapshotd_manager->IsAutoLoginConfigured()) {
-    data_snapshotd_manager->set_reset_autologin_callback(
-        base::BindOnce(&ExistingUserController::ResetAutoLoginTimer,
-                       weak_factory_.GetWeakPtr()));
-    return;
-  }
-
   // Start the auto-login timer.
   if (!auto_login_timer_)
     auto_login_timer_.reset(new base::OneShotTimer);
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
index 933606a..770fa04 100644
--- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -59,7 +59,6 @@
 #include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/settings/cros_settings_names.h"
 #include "chromeos/settings/cros_settings_provider.h"
-#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/cloud_policy_core.h"
@@ -109,8 +108,6 @@
 const char kHash[] = "test_hash";
 
 const char kPublicSessionUserEmail[] = "public_session_user@localhost";
-const char kPublicSessionSecondUserEmail[] =
-    "public_session_second_user@localhost";
 const int kAutoLoginNoDelay = 0;
 const int kAutoLoginShortDelay = 1;
 const int kAutoLoginLongDelay = 10000;
@@ -146,10 +143,6 @@
   return path.Append("kerberos").Append("krb5cc");
 }
 
-arc::data_snapshotd::ArcDataSnapshotdManager* arc_data_snapshotd_manager() {
-  return arc::data_snapshotd::ArcDataSnapshotdManager::Get();
-}
-
 }  // namespace
 
 class ExistingUserControllerTest : public policy::DevicePolicyCrosBrowserTest {
@@ -335,12 +328,6 @@
   void SetUpOnMainThread() override {
     ExistingUserControllerTest::SetUpOnMainThread();
 
-    // By default ArcDataSnapshotdManager does not influence an auto login
-    // flow.
-    EXPECT_TRUE(arc_data_snapshotd_manager());
-    EXPECT_TRUE(arc_data_snapshotd_manager()->IsAutoLoginAllowed());
-    EXPECT_FALSE(arc_data_snapshotd_manager()->IsAutoLoginConfigured());
-
     // Wait for the public session user to be created.
     if (!user_manager::UserManager::Get()->IsKnownUser(
             public_session_account_id_)) {
@@ -719,98 +706,6 @@
   FireAutoLogin();
 }
 
-IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest,
-                       ArcDataSnapshotdAutoLogin) {
-  arc_data_snapshotd_manager()->set_state_for_testing(
-      arc::data_snapshotd::ArcDataSnapshotdManager::State::kBlockedUi);
-  EXPECT_FALSE(arc_data_snapshotd_manager()->IsAutoLoginAllowed());
-  EXPECT_TRUE(arc_data_snapshotd_manager()->IsAutoLoginConfigured());
-
-  ConfigureAutoLogin();
-  existing_user_controller()->OnSigninScreenReady();
-
-  // Do not start an auto-login public account session when in blocked UI mode.
-  EXPECT_TRUE(auto_login_account_id().is_valid());
-  EXPECT_EQ(public_session_account_id_, auto_login_account_id());
-  EXPECT_EQ(0, auto_login_delay());
-  EXPECT_FALSE(auto_login_timer());
-
-  // Allow to launch public account session (MGS).
-  arc_data_snapshotd_manager()->set_state_for_testing(
-      arc::data_snapshotd::ArcDataSnapshotdManager::State::kMgsToLaunch);
-  EXPECT_TRUE(arc_data_snapshotd_manager()->IsAutoLoginAllowed());
-  EXPECT_TRUE(arc_data_snapshotd_manager()->IsAutoLoginConfigured());
-
-  // Set up mocks to check login success.
-  UserContext user_context(user_manager::USER_TYPE_PUBLIC_ACCOUNT,
-                           public_session_account_id_);
-  user_context.SetUserIDHash(user_context.GetAccountId().GetUserEmail());
-  ExpectSuccessfulLogin(user_context);
-  existing_user_controller()->OnSigninScreenReady();
-
-  // Start auto-login and wait for login tasks to complete.
-  content::RunAllPendingInMessageLoop();
-
-  arc_data_snapshotd_manager()->OnSessionStateChanged();
-
-  EXPECT_TRUE(auto_login_account_id().is_valid());
-  EXPECT_EQ(0, auto_login_delay());
-  EXPECT_TRUE(auto_login_timer());
-  EXPECT_EQ(arc::data_snapshotd::ArcDataSnapshotdManager::State::kMgsLaunched,
-            arc_data_snapshotd_manager()->state());
-}
-
-class ExistingUserControllerSecondPublicSessionTest
-    : public ExistingUserControllerPublicSessionTest {
- public:
-  void SetUpInProcessBrowserTestFixture() override {
-    ExistingUserControllerPublicSessionTest::SetUpInProcessBrowserTestFixture();
-    AddSecondPublicSessionAccount();
-  }
-
- private:
-  void AddSecondPublicSessionAccount() {
-    // Setup the device policy.
-    em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
-    em::DeviceLocalAccountInfoProto* account =
-        proto.mutable_device_local_accounts()->add_account();
-    account->set_account_id(kPublicSessionSecondUserEmail);
-    account->set_type(
-        em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_PUBLIC_SESSION);
-    RefreshDevicePolicy();
-
-    // Setup the device local account policy.
-    policy::UserPolicyBuilder device_local_account_policy;
-    device_local_account_policy.policy_data().set_username(
-        kPublicSessionSecondUserEmail);
-    device_local_account_policy.policy_data().set_policy_type(
-        policy::dm_protocol::kChromePublicAccountPolicyType);
-    device_local_account_policy.policy_data().set_settings_entity_id(
-        kPublicSessionSecondUserEmail);
-    device_local_account_policy.Build();
-    session_manager_client()->set_device_local_account_policy(
-        kPublicSessionSecondUserEmail, device_local_account_policy.GetBlob());
-  }
-};
-// Test that if two public session accounts are configured for the device, auto
-// login is not happening.
-IN_PROC_BROWSER_TEST_F(ExistingUserControllerSecondPublicSessionTest,
-                       ArcDataSnapshotdTwoAccounts) {
-  // Allow to launch public account session (MGS).
-  arc_data_snapshotd_manager()->set_state_for_testing(
-      arc::data_snapshotd::ArcDataSnapshotdManager::State::kMgsToLaunch);
-  EXPECT_TRUE(arc_data_snapshotd_manager()->IsAutoLoginAllowed());
-  EXPECT_TRUE(arc_data_snapshotd_manager()->IsAutoLoginConfigured());
-
-  ConfigureAutoLogin();
-  existing_user_controller()->OnSigninScreenReady();
-
-  // Do not configure auto login if more than one public session is configured.
-  EXPECT_FALSE(auto_login_account_id().is_valid());
-  EXPECT_EQ(0, auto_login_delay());
-  EXPECT_FALSE(auto_login_timer());
-}
-
 class ExistingUserControllerActiveDirectoryTest
     : public ExistingUserControllerTest {
  public:
diff --git a/chrome/browser/chromeos/login/version_updater/version_updater.cc b/chrome/browser/chromeos/login/version_updater/version_updater.cc
index 9965eba..c6fd97c 100644
--- a/chrome/browser/chromeos/login/version_updater/version_updater.cc
+++ b/chrome/browser/chromeos/login/version_updater/version_updater.cc
@@ -301,8 +301,7 @@
     is_first_detection_notification_ = false;
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce([]() {
-          network_portal_detector::GetInstance()->StartPortalDetection(
-              false /* force */);
+          network_portal_detector::GetInstance()->StartPortalDetection();
         }));
     return;
   }
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.cc b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
index 58db6437..a6d8c36f 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
@@ -97,7 +97,7 @@
                  content::NotificationService::AllSources());
 
   NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
-  StartPortalDetection(false /* force */);
+  StartPortalDetection();
 }
 
 NetworkPortalDetectorImpl::~NetworkPortalDetectorImpl() {
@@ -173,14 +173,11 @@
   return it->second;
 }
 
-bool NetworkPortalDetectorImpl::StartPortalDetection(bool force) {
-  if (!is_idle()) {
-    if (!force)
-      return false;
-    StopDetection();
-  }
+void NetworkPortalDetectorImpl::StartPortalDetection() {
+  if (!is_idle())
+    return;
   StartDetection();
-  return true;
+  return;
 }
 
 void NetworkPortalDetectorImpl::SetStrategy(
@@ -188,7 +185,9 @@
   if (id == strategy_->Id())
     return;
   strategy_ = PortalDetectorStrategy::CreateById(id, this);
-  StartPortalDetection(true /* force */);
+  if (!is_idle())
+    StopDetection();
+  StartPortalDetection();
 }
 
 void NetworkPortalDetectorImpl::DefaultNetworkChanged(
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.h b/chrome/browser/chromeos/net/network_portal_detector_impl.h
index 51506ae9..566fe90 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl.h
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl.h
@@ -100,7 +100,7 @@
   CaptivePortalState GetCaptivePortalState(const std::string& guid) override;
   bool IsEnabled() override;
   void Enable(bool start_detection) override;
-  bool StartPortalDetection(bool force) override;
+  void StartPortalDetection() override;
   void SetStrategy(PortalDetectorStrategy::StrategyId id) override;
 
   // NetworkStateHandlerObserver implementation:
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc b/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
index a6999c7..4dadf2c1 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
@@ -169,8 +169,8 @@
     return network_portal_detector()->state();
   }
 
-  bool StartPortalDetection(bool force) {
-    return network_portal_detector()->StartPortalDetection(force);
+  void StartPortalDetection() {
+    network_portal_detector()->StartPortalDetection();
   }
 
   void enable_error_screen_strategy() {
@@ -771,7 +771,7 @@
   // First portal detection attempts determines ONLINE state.
   SetConnected(kStubWireless1);
   ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
-  ASSERT_FALSE(StartPortalDetection(false /* force */));
+  StartPortalDetection();
 
   CompleteURLFetch(net::OK, 204, nullptr);
 
diff --git a/chrome/browser/chromeos/net/network_portal_detector_test_impl.cc b/chrome/browser/chromeos/net/network_portal_detector_test_impl.cc
index 68033e4c..d92dbe94 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_test_impl.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_test_impl.cc
@@ -103,9 +103,9 @@
 void NetworkPortalDetectorTestImpl::Enable(bool start_detection) {
 }
 
-bool NetworkPortalDetectorTestImpl::StartPortalDetection(bool force) {
-  if (portal_detection_in_progress_ && !force)
-    return false;
+void NetworkPortalDetectorTestImpl::StartPortalDetection() {
+  if (portal_detection_in_progress_)
+    return;
 
   portal_detection_in_progress_ = true;
   std::vector<base::OnceClosure> callbacks =
@@ -113,7 +113,7 @@
   for (auto& callback : callbacks)
     std::move(callback).Run();
 
-  return true;
+  return;
 }
 
 void NetworkPortalDetectorTestImpl::SetStrategy(
diff --git a/chrome/browser/chromeos/net/network_portal_detector_test_impl.h b/chrome/browser/chromeos/net/network_portal_detector_test_impl.h
index 6c4f4b8b..ea0ceff 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_test_impl.h
+++ b/chrome/browser/chromeos/net/network_portal_detector_test_impl.h
@@ -43,7 +43,7 @@
       const std::string& service_path) override;
   bool IsEnabled() override;
   void Enable(bool start_detection) override;
-  bool StartPortalDetection(bool force) override;
+  void StartPortalDetection() override;
   void SetStrategy(PortalDetectorStrategy::StrategyId id) override;
 
   PortalDetectorStrategy::StrategyId strategy_id() const {
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.cc
index d0a247c..8cfba1e 100644
--- a/chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.cc
+++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.cc
@@ -25,33 +25,32 @@
   return PluginVmInstallerFactory::GetForProfile(profile_);
 }
 
-// TODO(okalitova): Remove logs.
+bool PluginVmImageDownloadClient::IsCurrentDownload(const std::string& guid) {
+  return guid == GetInstaller()->GetCurrentDownloadGuid();
+}
 
 void PluginVmImageDownloadClient::OnServiceInitialized(
     bool state_lost,
     const std::vector<download::DownloadMetaData>& downloads) {
-  VLOG(1) << __func__ << " called";
-  // TODO(okalitova): Manage downloads after sleep and log out.
+  // TODO(timloh): It appears that only completed downloads (aka previous
+  // successful installations) surface here, so this logic might not be needed.
   for (const auto& download : downloads) {
     VLOG(1) << "Download tracked by DownloadService: " << download.guid;
-    old_downloads_.insert(download.guid);
     DownloadServiceFactory::GetForKey(profile_->GetProfileKey())
         ->CancelDownload(download.guid);
   }
 }
 
 void PluginVmImageDownloadClient::OnServiceUnavailable() {
-  VLOG(1) << __func__ << " called";
 }
 
 void PluginVmImageDownloadClient::OnDownloadStarted(
     const std::string& guid,
     const std::vector<GURL>& url_chain,
     const scoped_refptr<const net::HttpResponseHeaders>& headers) {
-  VLOG(1) << __func__ << " called";
   // We do not want downloads that are tracked by download service from its
   // initialization to proceed.
-  if (old_downloads_.find(guid) != old_downloads_.end()) {
+  if (!IsCurrentDownload(guid)) {
     DownloadServiceFactory::GetForKey(profile_->GetProfileKey())
         ->CancelDownload(guid);
     return;
@@ -64,8 +63,7 @@
 void PluginVmImageDownloadClient::OnDownloadUpdated(const std::string& guid,
                                                     uint64_t bytes_uploaded,
                                                     uint64_t bytes_downloaded) {
-  DCHECK(old_downloads_.find(guid) == old_downloads_.end());
-  VLOG(1) << __func__ << " called";
+  DCHECK(IsCurrentDownload(guid));
   VLOG(1) << bytes_downloaded << " bytes downloaded";
   GetInstaller()->OnDownloadProgressUpdated(bytes_downloaded, content_length_);
 }
@@ -74,7 +72,6 @@
     const std::string& guid,
     const download::CompletionInfo& completion_info,
     download::Client::FailureReason clientReason) {
-  VLOG(1) << __func__ << " called";
   auto failureReason =
       PluginVmInstaller::FailureReason::DOWNLOAD_FAILED_UNKNOWN;
   switch (clientReason) {
@@ -100,22 +97,16 @@
       break;
   }
 
-  // We do not want to notify PluginVmInstaller about the status of downloads
-  // that are tracked by download service from its initialization.
-  if (old_downloads_.find(guid) != old_downloads_.end())
+  if (!IsCurrentDownload(guid))
     return;
 
-  if (clientReason == download::Client::FailureReason::CANCELLED)
-    GetInstaller()->OnDownloadCancelled();
-  else
-    GetInstaller()->OnDownloadFailed(failureReason);
+  GetInstaller()->OnDownloadFailed(failureReason);
 }
 
 void PluginVmImageDownloadClient::OnDownloadSucceeded(
     const std::string& guid,
     const download::CompletionInfo& completion_info) {
-  DCHECK(old_downloads_.find(guid) == old_downloads_.end());
-  VLOG(1) << __func__ << " called";
+  DCHECK(IsCurrentDownload(guid));
   VLOG(1) << "Downloaded file is in " << completion_info.path.value();
   GetInstaller()->OnDownloadCompleted(completion_info);
 }
@@ -123,15 +114,12 @@
 bool PluginVmImageDownloadClient::CanServiceRemoveDownloadedFile(
     const std::string& guid,
     bool force_delete) {
-  VLOG(1) << __func__ << " called";
   return true;
 }
 
 void PluginVmImageDownloadClient::GetUploadData(
     const std::string& guid,
     download::GetUploadDataCallback callback) {
-  DCHECK(old_downloads_.find(guid) == old_downloads_.end());
-  VLOG(1) << __func__ << " called";
   base::SequencedTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), nullptr));
 }
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.h b/chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.h
index 253cede..db9b05cc 100644
--- a/chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.h
+++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_image_download_client.h
@@ -28,11 +28,12 @@
   ~PluginVmImageDownloadClient() override;
 
  private:
-  std::set<std::string> old_downloads_;
   Profile* profile_ = nullptr;
   int64_t content_length_ = -1;
 
   PluginVmInstaller* GetInstaller();
+  // Returns false for cancelled downloads.
+  bool IsCurrentDownload(const std::string& guid);
 
   // download::Client implementation.
   void OnServiceInitialized(
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.cc
index b203299..9252444a 100644
--- a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.cc
+++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.cc
@@ -327,11 +327,11 @@
   if (using_drive_download_service_) {
     DCHECK(drive_download_service_);
     drive_download_service_->CancelDownload();
-    CancelFinished();
   } else {
-    // OnDownloadCancelled() is called after the download is cancelled.
     download_service_->CancelDownload(current_download_guid_);
+    current_download_guid_.clear();
   }
+  CancelFinished();
 }
 
 void PluginVmInstaller::OnDlcDownloadProgressUpdated(double progress) {
@@ -420,20 +420,6 @@
   StartImport();
 }
 
-void PluginVmInstaller::OnDownloadCancelled() {
-  DCHECK_EQ(state_, State::kCancelling);
-  DCHECK_EQ(installing_state_, InstallingState::kDownloadingImage);
-
-  RemoveTemporaryImageIfExists();
-  current_download_guid_.clear();
-  if (using_drive_download_service_) {
-    drive_download_service_->ResetState();
-    using_drive_download_service_ = false;
-  }
-
-  CancelFinished();
-}
-
 void PluginVmInstaller::OnDownloadFailed(FailureReason reason) {
   RemoveTemporaryImageIfExists();
   current_download_guid_.clear();
@@ -774,7 +760,7 @@
   downloaded_image_for_testing_ = downloaded_image;
 }
 
-std::string PluginVmInstaller::GetCurrentDownloadGuidForTesting() {
+std::string PluginVmInstaller::GetCurrentDownloadGuid() {
   return current_download_guid_;
 }
 
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.h b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.h
index 3762199..89c52d5 100644
--- a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.h
+++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.h
@@ -125,13 +125,12 @@
   void OnDlcDownloadCompleted(
       const chromeos::DlcserviceClient::InstallResult& install_result);
 
-  // Called by PluginVmImageDownloadClient, are not supposed to be used by other
-  // classes.
+  // Used by PluginVmImageDownloadClient and PluginVmDriveImageDownloadService,
+  // other classes should not call into here.
   void OnDownloadStarted();
   void OnDownloadProgressUpdated(uint64_t bytes_downloaded,
                                  int64_t content_length);
   void OnDownloadCompleted(const download::CompletionInfo& info);
-  void OnDownloadCancelled();
   void OnDownloadFailed(FailureReason reason);
 
   // ConciergeClient::DiskImageObserver:
@@ -155,7 +154,7 @@
   void SetDriveDownloadServiceForTesting(
       std::unique_ptr<PluginVmDriveImageDownloadService>
           drive_download_service);
-  std::string GetCurrentDownloadGuidForTesting();
+  std::string GetCurrentDownloadGuid();
 
  private:
   void CheckLicense();
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc
index 50e398c..2f4cbe0b 100644
--- a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc
+++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc
@@ -471,7 +471,7 @@
 
   StartAndRunUntil(InstallingState::kDownloadingImage);
 
-  std::string guid = installer_->GetCurrentDownloadGuidForTesting();
+  std::string guid = installer_->GetCurrentDownloadGuid();
   base::Optional<download::DownloadParams> params =
       download_service_->GetDownload(guid);
   ASSERT_TRUE(params.has_value());
@@ -536,7 +536,7 @@
   EXPECT_CALL(*observer_, OnError(FailureReason::DOWNLOAD_FAILED_ABORTED));
 
   StartAndRunUntil(InstallingState::kDownloadingImage);
-  std::string guid = installer_->GetCurrentDownloadGuidForTesting();
+  std::string guid = installer_->GetCurrentDownloadGuid();
   download_service_->SetFailedDownload(guid, false);
   task_environment_.RunUntilIdle();
   VerifyExpectations();
@@ -563,8 +563,6 @@
   StartAndRunUntil(InstallingState::kDownloadingImage);
   installer_->Cancel();
   task_environment_.RunUntilIdle();
-  // Finishing image processing as it should really happen.
-  installer_->OnDownloadCancelled();
 
   histogram_tester_->ExpectTotalCount(kPluginVmImageDownloadedSizeHistogram, 0);
   histogram_tester_->ExpectTotalCount(kFailureReasonHistogram, 0);
diff --git a/chrome/browser/chromeos/power/ml/smart_dim/BUILD.gn b/chrome/browser/chromeos/power/ml/smart_dim/BUILD.gn
index aa5a281..e17fb5b5 100644
--- a/chrome/browser/chromeos/power/ml/smart_dim/BUILD.gn
+++ b/chrome/browser/chromeos/power/ml/smart_dim/BUILD.gn
@@ -6,8 +6,6 @@
   public = [
     "metrics.h",
     "ml_agent.h",
-    "model.h",
-    "model_impl.h",
   ]
 
   sources = [
@@ -20,11 +18,6 @@
     "ml_agent.h",
     "ml_agent_util.cc",
     "ml_agent_util.h",
-    "ml_service_client.cc",
-    "ml_service_client.h",
-    "model.h",
-    "model_impl.cc",
-    "model_impl.h",
     "smart_dim_worker.cc",
     "smart_dim_worker.h",
   ]
diff --git a/chrome/browser/chromeos/power/ml/smart_dim/model.h b/chrome/browser/chromeos/power/ml/smart_dim/model.h
deleted file mode 100644
index 0037acd4..0000000
--- a/chrome/browser/chromeos/power/ml/smart_dim/model.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018 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_POWER_ML_SMART_DIM_MODEL_H_
-#define CHROME_BROWSER_CHROMEOS_POWER_ML_SMART_DIM_MODEL_H_
-
-#include "base/callback.h"
-#include "chrome/browser/chromeos/power/ml/user_activity_event.pb.h"
-
-namespace chromeos {
-namespace power {
-namespace ml {
-
-// Interface to indicate whether an upcoming screen dim should go ahead based on
-// whether user will remain inactive if screen is dimmed now.
-class SmartDimModel {
- public:
-  using DimDecisionCallback =
-      base::OnceCallback<void(UserActivityEvent::ModelPrediction)>;
-  virtual ~SmartDimModel() = default;
-
-  // Post a request to determine whether an upcoming dim should go ahead based
-  // on input |features|. When a decision is arrived at, run the callback
-  // specified by |dim_callback|. If this method is called again before it
-  // calls the previous callback, the previous callback will be canceled.
-  virtual void RequestDimDecision(const UserActivityEvent::Features& features,
-                                  DimDecisionCallback dim_callback) = 0;
-
-  // Cancel a previous dim decision request, if one is pending. If no dim
-  // decision request is pending, this function has no effect.
-  virtual void CancelPreviousRequest() = 0;
-};
-
-}  // namespace ml
-}  // namespace power
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_POWER_ML_SMART_DIM_MODEL_H_
diff --git a/chrome/browser/chromeos/power/ml/smart_dim/model_impl.cc b/chrome/browser/chromeos/power/ml/smart_dim/model_impl.cc
deleted file mode 100644
index 8c831da0..0000000
--- a/chrome/browser/chromeos/power/ml/smart_dim/model_impl.cc
+++ /dev/null
@@ -1,370 +0,0 @@
-// Copyright 2018 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/power/ml/smart_dim/model_impl.h"
-
-#include <cmath>
-#include <map>
-#include <string>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/metrics/field_trial_params.h"
-#include "base/optional.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
-#include "base/task_runner_util.h"
-#include "chrome/browser/chromeos/power/ml/user_activity_ukm_logger_helpers.h"
-#include "chrome/grit/browser_resources.h"
-#include "chromeos/constants/chromeos_features.h"
-#include "components/assist_ranker/example_preprocessing.h"
-#include "components/assist_ranker/proto/example_preprocessor.pb.h"
-#include "components/assist_ranker/proto/ranker_example.pb.h"
-#include "ui/base/resource/resource_bundle.h"
-
-namespace chromeos {
-namespace power {
-namespace ml {
-
-namespace {
-
-constexpr size_t k20181115ModelInputVectorSize = 343;
-constexpr size_t k20190521ModelInputVectorSize = 592;
-
-constexpr double k20181115ModelDefaultDimThreshold = -1.0;
-constexpr double k20190521ModelDefaultDimThreshold = -0.6;
-
-// Loads the preprocessor config protobuf, which will be used later to convert a
-// RankerExample to a vectorized float for inactivity score calculation. Returns
-// nullptr if cannot load or parse the config.
-std::unique_ptr<assist_ranker::ExamplePreprocessorConfig>
-LoadExamplePreprocessorConfig() {
-  auto config = std::make_unique<assist_ranker::ExamplePreprocessorConfig>();
-
-  const int res_id =
-      base::FeatureList::IsEnabled(features::kSmartDimModelV3)
-          ? IDR_SMART_DIM_20190521_EXAMPLE_PREPROCESSOR_CONFIG_PB
-          : IDR_SMART_DIM_20181115_EXAMPLE_PREPROCESSOR_CONFIG_PB;
-
-  scoped_refptr<base::RefCountedMemory> raw_config =
-      ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(res_id);
-  if (!raw_config || !raw_config->front()) {
-    LOG(ERROR) << "Failed to load SmartDimModel example preprocessor config.";
-    return nullptr;
-  }
-
-  if (!config->ParseFromArray(raw_config->front(), raw_config->size())) {
-    LOG(ERROR) << "Failed to parse SmartDimModel example preprocessor config.";
-    return nullptr;
-  }
-
-  return config;
-}
-
-// Populates |example| using |features|. Returns true if no error occurred.
-bool PopulateRankerExample(const UserActivityEvent::Features& features,
-                           assist_ranker::RankerExample* example) {
-  CHECK(example);
-
-  // Some features are bucketized before being logged to UKM. Hence training
-  // examples use bucketized values. We need to bucketize them here to ensure
-  // consistency.
-  // It's ok if a feature is missing from |features|, and we will not return
-  // false. But if a feature exists in |features|, then we expect it to have
-  // a bucketized version in |buckets|. If its bucketized version is missing
-  // from |buckets| then we return false.
-  const std::map<std::string, int> buckets =
-      UserActivityUkmLoggerBucketizer::BucketizeUserActivityEventFeatures(
-          features);
-
-  auto& ranker_example_features = *example->mutable_features();
-
-  if (features.has_battery_percent()) {
-    const auto it = buckets.find(kBatteryPercent);
-    if (it == buckets.end())
-      return false;
-    ranker_example_features[kBatteryPercent].set_int32_value(it->second);
-  }
-
-  if (features.has_device_management()) {
-    ranker_example_features["DeviceManagement"].set_int32_value(
-        features.device_management());
-  }
-
-  if (features.has_device_mode()) {
-    ranker_example_features["DeviceMode"].set_int32_value(
-        features.device_mode());
-  }
-
-  if (features.has_device_type()) {
-    ranker_example_features["DeviceType"].set_int32_value(
-        features.device_type());
-  }
-
-  if (features.has_key_events_in_last_hour()) {
-    const auto it = buckets.find(kKeyEventsInLastHour);
-    if (it == buckets.end())
-      return false;
-    ranker_example_features[kKeyEventsInLastHour].set_int32_value(it->second);
-  }
-
-  if (features.has_last_activity_day()) {
-    ranker_example_features["LastActivityDay"].set_int32_value(
-        features.last_activity_day());
-  }
-
-  if (features.has_last_activity_time_sec()) {
-    const auto it = buckets.find(kLastActivityTime);
-    if (it == buckets.end())
-      return false;
-    ranker_example_features[kLastActivityTime].set_int32_value(it->second);
-  }
-
-  if (features.has_last_user_activity_time_sec()) {
-    const auto it = buckets.find(kLastUserActivityTime);
-    if (it == buckets.end())
-      return false;
-    ranker_example_features[kLastUserActivityTime].set_int32_value(it->second);
-  }
-
-  if (features.has_mouse_events_in_last_hour()) {
-    const auto it = buckets.find(kMouseEventsInLastHour);
-    if (it == buckets.end())
-      return false;
-    ranker_example_features[kMouseEventsInLastHour].set_int32_value(it->second);
-  }
-
-  if (features.has_on_battery()) {
-    // This is an int value in the model.
-    ranker_example_features["OnBattery"].set_int32_value(features.on_battery());
-  }
-
-  ranker_example_features["PreviousNegativeActionsCount"].set_int32_value(
-      features.previous_negative_actions_count());
-  ranker_example_features["PreviousPositiveActionsCount"].set_int32_value(
-      features.previous_positive_actions_count());
-
-  ranker_example_features["RecentTimeActive"].set_int32_value(
-      features.recent_time_active_sec());
-
-  if (features.has_video_playing_time_sec()) {
-    const auto it = buckets.find(kRecentVideoPlayingTime);
-    if (it == buckets.end())
-      return false;
-    ranker_example_features[kRecentVideoPlayingTime].set_int32_value(
-        it->second);
-  }
-
-  if (features.has_on_to_dim_sec()) {
-    ranker_example_features["ScreenDimDelay"].set_int32_value(
-        features.on_to_dim_sec());
-  }
-
-  if (features.has_dim_to_screen_off_sec()) {
-    ranker_example_features["ScreenDimToOffDelay"].set_int32_value(
-        features.dim_to_screen_off_sec());
-  }
-
-  if (features.has_time_since_last_key_sec()) {
-    ranker_example_features["TimeSinceLastKey"].set_int32_value(
-        features.time_since_last_key_sec());
-  }
-
-  if (features.has_time_since_last_mouse_sec()) {
-    ranker_example_features["TimeSinceLastMouse"].set_int32_value(
-        features.time_since_last_mouse_sec());
-  }
-
-  if (features.has_time_since_video_ended_sec()) {
-    const auto it = buckets.find(kTimeSinceLastVideoEnded);
-    if (it == buckets.end())
-      return false;
-    ranker_example_features[kTimeSinceLastVideoEnded].set_int32_value(
-        it->second);
-  }
-
-  if (features.has_engagement_score()) {
-    ranker_example_features["SiteEngagementScore"].set_int32_value(
-        features.engagement_score());
-  }
-
-  if (features.has_has_form_entry()) {
-    ranker_example_features["HasFormEntry"].set_bool_value(
-        features.has_form_entry());
-  }
-
-  if (features.has_tab_domain()) {
-    ranker_example_features["TabDomain"].set_string_value(
-        features.tab_domain());
-    ranker_example_features["HasTabs"].set_bool_value(true);
-  } else {
-    ranker_example_features["HasTabs"].set_bool_value(false);
-  }
-
-  return true;
-}
-
-// Squashes |score| into range [0, 1] using sigmoid, and scales it to [0,100]
-// so that values can be easily logged.
-int ScoreToProbability(float score) {
-  const float sigmoid = 1.0f / (1.0f + exp(-score));
-  const int prob = floor(sigmoid * 100);
-  return prob;
-}
-
-
-// Returns "dim_threshold" from experiment parameter. Also logs status to UMA.
-float GetDimThreshold() {
-  const double default_threshold =
-      base::FeatureList::IsEnabled(features::kSmartDimModelV3)
-          ? k20190521ModelDefaultDimThreshold
-          : k20181115ModelDefaultDimThreshold;
-  const double dim_threshold = base::GetFieldTrialParamByFeatureAsDouble(
-      features::kUserActivityPrediction, "dim_threshold", default_threshold);
-  if (std::abs(dim_threshold - default_threshold) < 1e-10) {
-    LogPowerMLSmartDimParameterResult(
-        SmartDimParameterResult::kUseDefaultValue);
-  } else {
-    LogPowerMLSmartDimParameterResult(SmartDimParameterResult::kSuccess);
-  }
-  return dim_threshold;
-}
-
-}  // namespace
-
-SmartDimModelImpl::SmartDimModelImpl() = default;
-
-SmartDimModelImpl::~SmartDimModelImpl() = default;
-
-SmartDimModelResult SmartDimModelImpl::PreprocessInput(
-    const UserActivityEvent::Features& features,
-    std::vector<float>* vectorized_features) {
-  DCHECK(vectorized_features);
-  LazyInitialize();
-
-  if (!preprocessor_config_) {
-    return SmartDimModelResult::kPreprocessorInitializationFailed;
-  }
-
-  assist_ranker::RankerExample ranker_example;
-  if (!PopulateRankerExample(features, &ranker_example)) {
-    return SmartDimModelResult::kOtherError;
-  }
-
-  int preprocessor_error = assist_ranker::ExamplePreprocessor::Process(
-      *preprocessor_config_, &ranker_example, true);
-  // kNoFeatureIndexFound can occur normally (e.g., when the domain name
-  // isn't known to the model or a rarely seen enum value is used).
-  if (preprocessor_error != assist_ranker::ExamplePreprocessor::kSuccess &&
-      preprocessor_error !=
-          assist_ranker::ExamplePreprocessor::kNoFeatureIndexFound) {
-    return SmartDimModelResult::kPreprocessorOtherError;
-  }
-
-  const auto& extracted_features =
-      ranker_example.features()
-          .at(assist_ranker::ExamplePreprocessor::kVectorizedFeatureDefaultName)
-          .float_list()
-          .float_value();
-  vectorized_features->assign(extracted_features.begin(),
-                              extracted_features.end());
-
-  return SmartDimModelResult::kSuccess;
-}
-
-UserActivityEvent::ModelPrediction
-SmartDimModelImpl::CreatePredictionFromInactivityScore(float inactivity_score) {
-  UserActivityEvent::ModelPrediction prediction;
-  const float dim_threshold = GetDimThreshold();
-
-  prediction.set_decision_threshold(ScoreToProbability(dim_threshold));
-  prediction.set_inactivity_score(ScoreToProbability(inactivity_score));
-
-  if (inactivity_score >= dim_threshold) {
-    prediction.set_response(UserActivityEvent::ModelPrediction::DIM);
-  } else {
-    prediction.set_response(UserActivityEvent::ModelPrediction::NO_DIM);
-  }
-
-  return prediction;
-}
-
-void SmartDimModelImpl::ShouldDim(
-    const UserActivityEvent::Features& input_features,
-    DimDecisionCallback callback) {
-  UserActivityEvent::ModelPrediction prediction;
-  prediction.set_response(UserActivityEvent::ModelPrediction::MODEL_ERROR);
-
-  std::vector<float> vectorized_features;
-  auto preprocess_result =
-      PreprocessInput(input_features, &vectorized_features);
-  if (preprocess_result != SmartDimModelResult::kSuccess) {
-    LogPowerMLSmartDimModelResult(preprocess_result);
-    std::move(callback).Run(prediction);
-    return;
-  }
-
-  const size_t expected_size =
-      base::FeatureList::IsEnabled(features::kSmartDimModelV3)
-          ? k20190521ModelInputVectorSize
-          : k20181115ModelInputVectorSize;
-
-  if (vectorized_features.size() != expected_size) {
-    LOG(ERROR) << "Smart Dim vectorized features not of correct size.";
-    LogPowerMLSmartDimModelResult(
-        SmartDimModelResult::kMismatchedFeatureSizeError);
-    std::move(callback).Run(prediction);
-    return;
-  }
-
-  if (!ml_service_client_) {
-    LOG(ERROR) << "ML service Mojo client not initialized correctly";
-    LogPowerMLSmartDimModelResult(
-        SmartDimModelResult::kMlServiceInitializationFailedError);
-    std::move(callback).Run(prediction);
-    return;
-  }
-
-  ml_service_client_->DoInference(
-      vectorized_features,
-      base::Bind(&SmartDimModelImpl::CreatePredictionFromInactivityScore,
-                 base::Unretained(this)),
-      std::move(callback));
-}
-
-void SmartDimModelImpl::RequestDimDecision(
-    const UserActivityEvent::Features& input_features,
-    DimDecisionCallback dim_callback) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  // Cancel previously assigned callbacks and set it to the new callback.
-  cancelable_callback_.Reset(std::move(dim_callback));
-  ShouldDim(input_features, cancelable_callback_.callback());
-}
-
-void SmartDimModelImpl::CancelPreviousRequest() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  cancelable_callback_.Cancel();
-}
-
-void SmartDimModelImpl::SetMlServiceClientForTesting(
-    std::unique_ptr<MlServiceClient> client) {
-  DCHECK(!ml_service_client_);
-  ml_service_client_ = std::move(client);
-}
-
-void SmartDimModelImpl::LazyInitialize() {
-  if (!ml_service_client_) {
-    ml_service_client_ = CreateMlServiceClient();
-  }
-
-  if (!preprocessor_config_) {
-    preprocessor_config_ = LoadExamplePreprocessorConfig();
-  }
-}
-
-}  // namespace ml
-}  // namespace power
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/power/ml/smart_dim/model_impl.h b/chrome/browser/chromeos/power/ml/smart_dim/model_impl.h
deleted file mode 100644
index db07fa6..0000000
--- a/chrome/browser/chromeos/power/ml/smart_dim/model_impl.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2018 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_POWER_ML_SMART_DIM_MODEL_IMPL_H_
-#define CHROME_BROWSER_CHROMEOS_POWER_ML_SMART_DIM_MODEL_IMPL_H_
-
-#include <memory>
-
-#include "base/cancelable_callback.h"
-#include "base/macros.h"
-#include "base/sequenced_task_runner.h"
-#include "base/time/time.h"
-#include "chrome/browser/chromeos/power/ml/smart_dim/metrics.h"
-#include "chrome/browser/chromeos/power/ml/smart_dim/ml_service_client.h"
-#include "chrome/browser/chromeos/power/ml/smart_dim/model.h"
-
-namespace assist_ranker {
-class ExamplePreprocessorConfig;
-}  // namespace assist_ranker
-
-namespace chromeos {
-namespace power {
-namespace ml {
-
-// Real implementation of SmartDimModel that predicts whether an upcoming screen
-// dim should go ahead based on user activity/inactivity following dim.
-class SmartDimModelImpl : public SmartDimModel {
- public:
-  SmartDimModelImpl();
-  ~SmartDimModelImpl() override;
-
-  // chromeos::power::ml::SmartDimModel overrides:
-  void RequestDimDecision(const UserActivityEvent::Features& features,
-                          DimDecisionCallback dim_callback) override;
-  void CancelPreviousRequest() override;
-
-  // Override MlServiceClient in a unit test environment where there is no real
-  // ML Service daemon to connect to.
-  void SetMlServiceClientForTesting(std::unique_ptr<MlServiceClient> client);
-
- private:
-  // Loads the preprocessor config if not already loaded. Also initializes the
-  // MlServiceClient object.
-  void LazyInitialize();
-
-  // Pre-processes the input features into a vector, placed in
-  // |*vectorized_features|, which is consumable by the ML model.
-  //
-  // Returns SmartDimModelResult::kSuccess on success, and the appropriate
-  // error on failure.
-  SmartDimModelResult PreprocessInput(
-      const UserActivityEvent::Features& features,
-      std::vector<float>* vectorized_features);
-
-  // Takes an |inactivity_score| returned from the ML model and, using that,
-  // returns a ModelPrediction.
-  UserActivityEvent::ModelPrediction CreatePredictionFromInactivityScore(
-      float inactivity_score);
-
-  // Calls the ML service Mojo API to perform an Smart Dim inference call,
-  // given |input_features|. The |callback| is supplied to the Mojo API,
-  // which in turn will call it to provide the result (a ModelPrediction), once
-  // the inference is complete.
-  void ShouldDim(const UserActivityEvent::Features& input_features,
-                 DimDecisionCallback callback);
-
-  std::unique_ptr<assist_ranker::ExamplePreprocessorConfig>
-      preprocessor_config_;
-
-  // Cancelable wrapper for the DimDecisionCallback passed by the client to
-  // RequestDimDecision().
-  base::CancelableOnceCallback<void(UserActivityEvent::ModelPrediction)>
-      cancelable_callback_;
-
-  // Pointer to the object that handles the ML service calls.
-  std::unique_ptr<MlServiceClient> ml_service_client_;
-
-  SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(SmartDimModelImpl);
-};
-
-}  // namespace ml
-}  // namespace power
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_POWER_ML_SMART_DIM_MODEL_IMPL_H_
diff --git a/chrome/browser/chromeos/power/ml/smart_dim/model_unittest.cc b/chrome/browser/chromeos/power/ml/smart_dim/model_unittest.cc
deleted file mode 100644
index 11527d5..0000000
--- a/chrome/browser/chromeos/power/ml/smart_dim/model_unittest.cc
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright 2018 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/power/ml/smart_dim/model_impl.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/task_environment.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/time/time.h"
-#include "chrome/browser/chromeos/power/ml/user_activity_event.pb.h"
-#include "chromeos/constants/chromeos_features.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/page_transition_types.h"
-
-namespace chromeos {
-namespace power {
-namespace ml {
-
-namespace {
-
-// Arbitrary inactivity score for the fake ML Service client to return:
-constexpr float kTestInactivityScore = -3.7;
-// Quantized into the range [0, 100] via sigmoid transform:
-constexpr int kQuantizedTestInactivityScore = 2;
-
-// Arbitrary dim thresholds lower/higher than kTestInactivityScore, implying
-// no/yes dim decisions respectively.
-constexpr double kLowDimThreshold = -10.0;
-constexpr double kHighDimThreshold = -0.1;
-// Same values quantized into the range [0, 100] via sigmoid transform:
-constexpr int kQuantizedLowDimThreshold = 0;
-constexpr int kQuantizedHighDimThreshold = 47;
-
-UserActivityEvent::Features DefaultFeatures() {
-  UserActivityEvent::Features features;
-  // Bucketize to 95.
-  features.set_battery_percent(96.0);
-  features.set_device_management(UserActivityEvent::Features::UNMANAGED);
-  features.set_device_mode(UserActivityEvent::Features::CLAMSHELL);
-  features.set_device_type(UserActivityEvent::Features::CHROMEBOOK);
-  // Bucketize to 200.
-  features.set_key_events_in_last_hour(290);
-  features.set_last_activity_day(UserActivityEvent::Features::THU);
-  // Bucketize to 7.
-  features.set_last_activity_time_sec(25920);
-  // Bucketize to 7.
-  features.set_last_user_activity_time_sec(25920);
-  // Bucketize to 2000.
-  features.set_mouse_events_in_last_hour(2600);
-  features.set_on_battery(false);
-  features.set_previous_negative_actions_count(3);
-  features.set_previous_positive_actions_count(0);
-  features.set_recent_time_active_sec(190);
-  features.set_video_playing_time_sec(0);
-  features.set_on_to_dim_sec(30);
-  features.set_dim_to_screen_off_sec(10);
-  features.set_time_since_last_key_sec(30);
-  features.set_time_since_last_mouse_sec(688);
-  // Bucketize to 900.
-  features.set_time_since_video_ended_sec(1100);
-  features.set_has_form_entry(false);
-  features.set_source_id(123);  // not used.
-  features.set_engagement_score(40);
-  features.set_tab_domain("//mail.google.com");
-  return features;
-}
-
-// Class to hold scoped local modifications to Smart-dim related feature flags.
-class SmartDimFeatureFlags {
- public:
-  SmartDimFeatureFlags() = default;
-
-  void Initialize(const double dim_threshold) {
-    const std::map<std::string, std::string> params = {
-        {"dim_threshold", base::NumberToString(dim_threshold)}};
-    smart_dim_feature_override_.InitAndEnableFeatureWithParameters(
-        features::kUserActivityPrediction, params);
-  }
-
- private:
-  base::test::ScopedFeatureList smart_dim_feature_override_;
-
-  DISALLOW_COPY_AND_ASSIGN(SmartDimFeatureFlags);
-};
-
-class FakeMlServiceClient : public MlServiceClient {
- public:
-  FakeMlServiceClient() = default;
-  ~FakeMlServiceClient() override {}
-
-  // MlServiceClient:
-  void DoInference(
-      const std::vector<float>& features,
-      base::RepeatingCallback<UserActivityEvent::ModelPrediction(float)>
-          get_prediction_callback,
-      SmartDimModel::DimDecisionCallback decision_callback) override {
-    const float inactivity_score = kTestInactivityScore;
-
-    UserActivityEvent::ModelPrediction model_prediction =
-        get_prediction_callback.Run(inactivity_score);
-    base::SequencedTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(std::move(decision_callback), model_prediction));
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(FakeMlServiceClient);
-};
-
-}  // namespace
-
-class SmartDimModelImplTest : public testing::Test {
- public:
-  SmartDimModelImplTest()
-      : task_environment_(
-            base::test::TaskEnvironment::MainThreadType::IO,
-            base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {}
-
-  ~SmartDimModelImplTest() override = default;
-
- protected:
-  // Sets a fake MlServiceClient into |impl|.
-  void InjectFakeMlServiceClient(SmartDimModelImpl* const impl) {
-    impl->SetMlServiceClientForTesting(std::make_unique<FakeMlServiceClient>());
-  }
-
-  base::test::TaskEnvironment task_environment_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SmartDimModelImplTest);
-};
-
-// With a high dim threshold, NO_DIM decision is expected.
-TEST_F(SmartDimModelImplTest, ShouldNotDim) {
-  SmartDimFeatureFlags flags;
-  flags.Initialize(kHighDimThreshold);
-
-  SmartDimModelImpl smart_dim_model;
-  InjectFakeMlServiceClient(&smart_dim_model);
-
-  bool callback_done = false;
-  smart_dim_model.RequestDimDecision(
-      DefaultFeatures(), base::BindOnce(
-                             [](bool* callback_done,
-                                UserActivityEvent::ModelPrediction prediction) {
-                               EXPECT_EQ(
-                                   UserActivityEvent::ModelPrediction::NO_DIM,
-                                   prediction.response());
-                               EXPECT_EQ(kQuantizedHighDimThreshold,
-                                         prediction.decision_threshold());
-                               EXPECT_EQ(kQuantizedTestInactivityScore,
-                                         prediction.inactivity_score());
-                               *callback_done = true;
-                             },
-                             &callback_done));
-  task_environment_.RunUntilIdle();
-  EXPECT_TRUE(callback_done);
-}
-
-// With a low dim threshold, DIM decision is expected.
-TEST_F(SmartDimModelImplTest, ShouldDim) {
-  SmartDimFeatureFlags flags;
-  flags.Initialize(kLowDimThreshold);
-
-  SmartDimModelImpl smart_dim_model;
-  InjectFakeMlServiceClient(&smart_dim_model);
-
-  bool callback_done = false;
-  smart_dim_model.RequestDimDecision(
-      DefaultFeatures(), base::BindOnce(
-                             [](bool* callback_done,
-                                UserActivityEvent::ModelPrediction prediction) {
-                               EXPECT_EQ(
-                                   UserActivityEvent::ModelPrediction::DIM,
-                                   prediction.response());
-                               EXPECT_EQ(kQuantizedLowDimThreshold,
-                                         prediction.decision_threshold());
-                               EXPECT_EQ(kQuantizedTestInactivityScore,
-                                         prediction.inactivity_score());
-                               *callback_done = true;
-                             },
-                             &callback_done));
-  task_environment_.RunUntilIdle();
-  EXPECT_TRUE(callback_done);
-}
-
-// Check that CancelableCallback ensures a callback doesn't execute twice, in
-// case two RequestDimDecision() calls were made before any callback ran.
-TEST_F(SmartDimModelImplTest, CheckCancelableCallback) {
-  SmartDimFeatureFlags flags;
-  flags.Initialize(kLowDimThreshold);
-
-  SmartDimModelImpl smart_dim_model;
-  InjectFakeMlServiceClient(&smart_dim_model);
-
-  bool callback_done = false;
-  int num_callbacks_run = 0;
-  for (int i = 0; i < 2; i++) {
-    smart_dim_model.RequestDimDecision(
-        DefaultFeatures(),
-        base::BindOnce(
-            [](bool* callback_done, int* num_callbacks_run,
-               UserActivityEvent::ModelPrediction prediction) {
-              EXPECT_EQ(UserActivityEvent::ModelPrediction::DIM,
-                        prediction.response());
-              EXPECT_EQ(kQuantizedLowDimThreshold,
-                        prediction.decision_threshold());
-              EXPECT_EQ(kQuantizedTestInactivityScore,
-                        prediction.inactivity_score());
-              *callback_done = true;
-              (*num_callbacks_run)++;
-            },
-            &callback_done, &num_callbacks_run));
-  }
-  task_environment_.RunUntilIdle();
-  EXPECT_TRUE(callback_done);
-  EXPECT_EQ(1, num_callbacks_run);
-}
-
-// Check that CancelPreviousRequest() can successfully prevent a previous
-// requested dim decision request from running.
-TEST_F(SmartDimModelImplTest, CheckCanceledRequest) {
-  SmartDimFeatureFlags flags;
-  flags.Initialize(kLowDimThreshold);
-
-  SmartDimModelImpl smart_dim_model;
-  InjectFakeMlServiceClient(&smart_dim_model);
-
-  bool callback_done = false;
-  smart_dim_model.RequestDimDecision(
-      DefaultFeatures(), base::BindOnce(
-                             [](bool* callback_done,
-                                UserActivityEvent::ModelPrediction prediction) {
-                               *callback_done = true;
-                             },
-                             &callback_done));
-  smart_dim_model.CancelPreviousRequest();
-  task_environment_.RunUntilIdle();
-  EXPECT_FALSE(callback_done);
-}
-
-}  // namespace ml
-}  // namespace power
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/power/ml/user_activity_controller.cc b/chrome/browser/chromeos/power/ml/user_activity_controller.cc
index 596e95a..882d3508 100644
--- a/chrome/browser/chromeos/power/ml/user_activity_controller.cc
+++ b/chrome/browser/chromeos/power/ml/user_activity_controller.cc
@@ -51,7 +51,7 @@
       &user_activity_ukm_logger_, detector, power_manager_client,
       session_manager,
       video_observer_user_logger.InitWithNewPipeAndPassReceiver(),
-      chromeos::ChromeUserManager::Get(), &smart_dim_model_);
+      chromeos::ChromeUserManager::Get());
   aura::Env::GetInstance()
       ->context_factory()
       ->GetHostFrameSinkManager()
diff --git a/chrome/browser/chromeos/power/ml/user_activity_controller.h b/chrome/browser/chromeos/power/ml/user_activity_controller.h
index 30e2ba0..7a6f7d4 100644
--- a/chrome/browser/chromeos/power/ml/user_activity_controller.h
+++ b/chrome/browser/chromeos/power/ml/user_activity_controller.h
@@ -9,7 +9,6 @@
 
 #include "base/callback.h"
 #include "chrome/browser/chromeos/power/ml/idle_event_notifier.h"
-#include "chrome/browser/chromeos/power/ml/smart_dim/model_impl.h"
 #include "chrome/browser/chromeos/power/ml/user_activity_manager.h"
 #include "chrome/browser/chromeos/power/ml/user_activity_ukm_logger_impl.h"
 
@@ -33,7 +32,6 @@
   std::unique_ptr<IdleEventNotifier> idle_event_notifier_;
   UserActivityUkmLoggerImpl user_activity_ukm_logger_;
   std::unique_ptr<UserActivityManager> user_activity_manager_;
-  SmartDimModelImpl smart_dim_model_;
 
   DISALLOW_COPY_AND_ASSIGN(UserActivityController);
 };
diff --git a/chrome/browser/chromeos/power/ml/user_activity_manager.cc b/chrome/browser/chromeos/power/ml/user_activity_manager.cc
index b928e461..4838cee5 100644
--- a/chrome/browser/chromeos/power/ml/user_activity_manager.cc
+++ b/chrome/browser/chromeos/power/ml/user_activity_manager.cc
@@ -105,10 +105,8 @@
     chromeos::PowerManagerClient* power_manager_client,
     session_manager::SessionManager* session_manager,
     mojo::PendingReceiver<viz::mojom::VideoDetectorObserver> receiver,
-    const chromeos::ChromeUserManager* user_manager,
-    SmartDimModel* smart_dim_model)
+    const chromeos::ChromeUserManager* user_manager)
     : ukm_logger_(ukm_logger),
-      smart_dim_model_(smart_dim_model),
       user_activity_observer_(this),
       power_manager_client_observer_(this),
       session_manager_observer_(this),
@@ -263,19 +261,14 @@
         profile->GetPrefs()->GetBoolean(ash::prefs::kPowerSmartDimEnabled);
   }
   if (smart_dim_enabled &&
-      base::FeatureList::IsEnabled(features::kUserActivityPrediction) &&
-      SmartDimModelReady()) {
+      base::FeatureList::IsEnabled(features::kUserActivityPrediction)) {
     waiting_for_model_decision_ = true;
     time_dim_decision_requested_ = base::TimeTicks::Now();
     auto request_callback =
         base::BindOnce(&UserActivityManager::HandleSmartDimDecision,
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback));
-    if (base::FeatureList::IsEnabled(features::kSmartDimNewMlAgent))
-      SmartDimMlAgent::GetInstance()->RequestDimDecision(
-          features_, std::move(request_callback));
-    else
-      smart_dim_model_->RequestDimDecision(features_,
-                                           std::move(request_callback));
+    SmartDimMlAgent::GetInstance()->RequestDimDecision(
+        features_, std::move(request_callback));
   }
   waiting_for_final_action_ = true;
 }
@@ -560,8 +553,7 @@
     const base::TimeDelta& now) {
   PreviousEventLoggingResult result = PreviousEventLoggingResult::kSuccess;
   if (!model_prediction_) {
-    result = base::FeatureList::IsEnabled(features::kUserActivityPrediction) &&
-                     SmartDimModelReady()
+    result = base::FeatureList::IsEnabled(features::kUserActivityPrediction)
                  ? PreviousEventLoggingResult::kErrorModelPredictionMissing
                  : PreviousEventLoggingResult::kErrorModelDisabled;
     LogPowerMLPreviousEventLoggingResult(result);
@@ -605,10 +597,7 @@
 
 void UserActivityManager::CancelDimDecisionRequest() {
   LOG(WARNING) << "Cancelling pending Smart Dim decision request.";
-  if (base::FeatureList::IsEnabled(features::kSmartDimNewMlAgent))
-    SmartDimMlAgent::GetInstance()->CancelPreviousRequest();
-  else
-    smart_dim_model_->CancelPreviousRequest();
+  SmartDimMlAgent::GetInstance()->CancelPreviousRequest();
 
   waiting_for_model_decision_ = false;
   const base::TimeDelta wait_time =
@@ -617,13 +606,6 @@
   time_dim_decision_requested_ = base::TimeTicks();
 }
 
-bool UserActivityManager::SmartDimModelReady() {
-  // We assume that BuiltinWorker of SmartDimMlAgent can always load model and
-  // preprocessor config from rootfs, therefore SmartDimMlAgent is always ready.
-  return base::FeatureList::IsEnabled(features::kSmartDimNewMlAgent) ||
-         smart_dim_model_;
-}
-
 }  // namespace ml
 }  // namespace power
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/power/ml/user_activity_manager.h b/chrome/browser/chromeos/power/ml/user_activity_manager.h
index aa211a03..b628bf0 100644
--- a/chrome/browser/chromeos/power/ml/user_activity_manager.h
+++ b/chrome/browser/chromeos/power/ml/user_activity_manager.h
@@ -13,7 +13,6 @@
 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
 #include "chrome/browser/chromeos/power/ml/boot_clock.h"
 #include "chrome/browser/chromeos/power/ml/idle_event_notifier.h"
-#include "chrome/browser/chromeos/power/ml/smart_dim/model.h"
 #include "chrome/browser/chromeos/power/ml/user_activity_event.pb.h"
 #include "chrome/browser/chromeos/power/ml/user_activity_ukm_logger.h"
 #include "chrome/browser/resource_coordinator/tab_metrics_event.pb.h"
@@ -85,8 +84,7 @@
       chromeos::PowerManagerClient* power_manager_client,
       session_manager::SessionManager* session_manager,
       mojo::PendingReceiver<viz::mojom::VideoDetectorObserver> receiver,
-      const chromeos::ChromeUserManager* user_manager,
-      SmartDimModel* smart_dim_model);
+      const chromeos::ChromeUserManager* user_manager);
   ~UserActivityManager() override;
 
   // ui::UserActivityObserver overrides.
@@ -155,12 +153,9 @@
 
   void ResetAfterLogging();
 
-  // Cancel any pending request to |smart_dim_model_| to get a dim decision.
+  // Cancel any pending request to `SmartDimMlAgent` to get a dim decision.
   void CancelDimDecisionRequest();
 
-  // If old smart dim model or new SmartDimMlAgent is ready, based on Finch.
-  bool SmartDimModelReady();
-
   // Time when an idle event is received and we start logging. Null if an idle
   // event hasn't been observed.
   base::Optional<base::TimeDelta> idle_event_start_since_boot_;
@@ -190,8 +185,6 @@
 
   UserActivityUkmLogger* const ukm_logger_;
 
-  SmartDimModel* const smart_dim_model_;
-
   ScopedObserver<ui::UserActivityDetector, ui::UserActivityObserver>
       user_activity_observer_;
   ScopedObserver<chromeos::PowerManagerClient,
@@ -235,7 +228,7 @@
   // set to true after we've received an idle event, but haven't received final
   // action to log the event.
   bool waiting_for_final_action_ = false;
-  // Whether we are waiting for a decision from the |smart_dim_model_|
+  // Whether we are waiting for a decision from the `SmartDimMlAgent`
   // regarding whether to proceed with a dim or not. It is only set
   // to true in OnIdleEventObserved() when we request a dim decision.
   bool waiting_for_model_decision_ = false;
diff --git a/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc b/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
index 22af99c..d645591 100644
--- a/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
+++ b/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/chromeos/power/ml/idle_event_notifier.h"
 #include "chrome/browser/chromeos/power/ml/smart_dim/ml_agent.h"
-#include "chrome/browser/chromeos/power/ml/smart_dim/model.h"
 #include "chrome/browser/chromeos/power/ml/user_activity_event.pb.h"
 #include "chrome/browser/chromeos/power/ml/user_activity_ukm_logger.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
@@ -104,80 +103,13 @@
   DISALLOW_COPY_AND_ASSIGN(TestingUserActivityUkmLogger);
 };
 
-// Testing smart dim model.
-class FakeSmartDimModel : public SmartDimModel {
- public:
-  explicit FakeSmartDimModel(
-      const scoped_refptr<base::SequencedTaskRunner> runner)
-      : task_runner_(runner) {}
-  ~FakeSmartDimModel() override = default;
-
-  void set_inactivity_score(const int inactivity_score) {
-    inactivity_score_ = inactivity_score;
-  }
-
-  void set_decision_threshold(const int decision_threshold) {
-    decision_threshold_ = decision_threshold;
-  }
-
-  UserActivityEvent::ModelPrediction ShouldDim(
-      const UserActivityEvent::Features& input_features) {
-    UserActivityEvent::ModelPrediction model_prediction;
-    // If either of these two values are set outside of the legal range [0,100],
-    // return an error code.
-    // The |model_applied| field is not filled by the model but by
-    // UserActivityManager.
-    if (inactivity_score_ < 0 || inactivity_score_ > 100 ||
-        decision_threshold_ < 0 || decision_threshold_ > 100) {
-      model_prediction.set_response(
-          UserActivityEvent::ModelPrediction::MODEL_ERROR);
-    } else {
-      model_prediction.set_decision_threshold(decision_threshold_);
-      model_prediction.set_inactivity_score(inactivity_score_);
-      if (inactivity_score_ < decision_threshold_) {
-        model_prediction.set_response(
-            UserActivityEvent::ModelPrediction::NO_DIM);
-      } else {
-        model_prediction.set_response(UserActivityEvent::ModelPrediction::DIM);
-      }
-    }
-    return model_prediction;
-  }
-
-  // SmartDimModel overrides:
-  void RequestDimDecision(const UserActivityEvent::Features& features,
-                          DimDecisionCallback dim_callback) override {
-    // Cancel previously assigned callbacks and set it to the new callback.
-    cancelable_callback_.Reset(std::move(dim_callback));
-    base::PostTaskAndReplyWithResult(
-        task_runner_.get(), FROM_HERE,
-        base::BindOnce(&FakeSmartDimModel::ShouldDim, base::Unretained(this),
-                       features),
-        base::BindOnce(cancelable_callback_.callback()));
-  }
-
-  // TODO(crbug.com/893425): Add unit tests that test this API.
-  void CancelPreviousRequest() override { cancelable_callback_.Cancel(); }
-
- private:
-  int inactivity_score_ = -1;
-  int decision_threshold_ = -1;
-  const scoped_refptr<base::SequencedTaskRunner> task_runner_;
-  base::CancelableOnceCallback<void(UserActivityEvent::ModelPrediction)>
-      cancelable_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeSmartDimModel);
-};
-
-class UserActivityManagerTest : public ChromeRenderViewHostTestHarness,
-                                public ::testing::WithParamInterface<bool> {
+class UserActivityManagerTest : public ChromeRenderViewHostTestHarness {
  public:
   UserActivityManagerTest()
       : ChromeRenderViewHostTestHarness(
             base::test::TaskEnvironment::MainThreadType::UI,
             base::test::TaskEnvironment::TimeSource::MOCK_TIME,
-            base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED),
-        model_(task_environment()->GetMainThreadTaskRunner()) {}
+            base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {}
 
   ~UserActivityManagerTest() override = default;
 
@@ -190,11 +122,10 @@
     activity_logger_ = std::make_unique<UserActivityManager>(
         &delegate_, &user_activity_detector_, PowerManagerClient::Get(),
         &session_manager_, observer.InitWithNewPipeAndPassReceiver(),
-        &fake_user_manager_, &model_);
+        &fake_user_manager_);
 
     machine_learning::ServiceConnection::UseFakeServiceConnectionForTesting(
         &fake_service_connection_);
-    use_new_ml_agent_ = GetParam();
   }
 
   void TearDown() override {
@@ -328,13 +259,11 @@
   }
 
   TestingUserActivityUkmLogger delegate_;
-  FakeSmartDimModel model_;
   chromeos::FakeChromeUserManager fake_user_manager_;
   // Only used to get SourceIds for URLs.
   ukm::TestAutoSetUkmRecorder ukm_recorder_;
   TabActivitySimulator tab_activity_simulator_;
   machine_learning::FakeServiceConnectionImpl fake_service_connection_;
-  bool use_new_ml_agent_;
 
   const GURL url1_ = GURL("https://example1.com/");
   const GURL url2_ = GURL("https://example2.com/");
@@ -352,7 +281,7 @@
 
 // After an idle event, we have a ui::Event, we should expect one
 // UserActivityEvent.
-TEST_P(UserActivityManagerTest, LogAfterIdleEvent) {
+TEST_F(UserActivityManagerTest, LogAfterIdleEvent) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -379,7 +308,7 @@
 }
 
 // Get a user event before an idle event, we should not log it.
-TEST_P(UserActivityManagerTest, LogBeforeIdleEvent) {
+TEST_F(UserActivityManagerTest, LogBeforeIdleEvent) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -393,7 +322,7 @@
 
 // Get a user event, then an idle event, then another user event,
 // we should log the last one.
-TEST_P(UserActivityManagerTest, LogSecondEvent) {
+TEST_F(UserActivityManagerTest, LogSecondEvent) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -421,7 +350,7 @@
 }
 
 // Log multiple events.
-TEST_P(UserActivityManagerTest, LogMultipleEvents) {
+TEST_F(UserActivityManagerTest, LogMultipleEvents) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -506,7 +435,7 @@
   EXPECT_EQ(2, events[3].features().previous_negative_actions_count());
 }
 
-TEST_P(UserActivityManagerTest, UserCloseLid) {
+TEST_F(UserActivityManagerTest, UserCloseLid) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -521,7 +450,7 @@
   EXPECT_TRUE(events.empty());
 }
 
-TEST_P(UserActivityManagerTest, PowerChangeActivity) {
+TEST_F(UserActivityManagerTest, PowerChangeActivity) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -547,7 +476,7 @@
   EqualEvent(expected_event, events[0].event());
 }
 
-TEST_P(UserActivityManagerTest, VideoActivity) {
+TEST_F(UserActivityManagerTest, VideoActivity) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -571,7 +500,7 @@
 
 // System remains idle, screen is dimmed then turned off, and system is finally
 // suspended.
-TEST_P(UserActivityManagerTest, SystemIdleSuspend) {
+TEST_F(UserActivityManagerTest, SystemIdleSuspend) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -600,7 +529,7 @@
 
 // System remains idle, screen is dimmed then turned off, but system is not
 // suspended.
-TEST_P(UserActivityManagerTest, SystemIdleNotSuspend) {
+TEST_F(UserActivityManagerTest, SystemIdleNotSuspend) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -619,7 +548,7 @@
 
 // Test system idle interrupt by user activity.
 // We should only observe user activity.
-TEST_P(UserActivityManagerTest, SystemIdleInterrupted) {
+TEST_F(UserActivityManagerTest, SystemIdleInterrupted) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -649,7 +578,7 @@
   EqualEvent(expected_event, events[0].event());
 }
 
-TEST_P(UserActivityManagerTest, ScreenLockNoSuspend) {
+TEST_F(UserActivityManagerTest, ScreenLockNoSuspend) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -662,7 +591,7 @@
   ASSERT_EQ(0U, events.size());
 }
 
-TEST_P(UserActivityManagerTest, ScreenLockWithSuspend) {
+TEST_F(UserActivityManagerTest, ScreenLockWithSuspend) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -689,7 +618,7 @@
 
 // As we log when SuspendImminent is received, sleep duration from SuspendDone
 // doesn't make any difference.
-TEST_P(UserActivityManagerTest, SuspendIdleShortSleepDuration) {
+TEST_F(UserActivityManagerTest, SuspendIdleShortSleepDuration) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -713,7 +642,7 @@
   EqualEvent(expected_event, events[0].event());
 }
 
-TEST_P(UserActivityManagerTest, SuspendLidClosed) {
+TEST_F(UserActivityManagerTest, SuspendLidClosed) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -736,7 +665,7 @@
   EqualEvent(expected_event, events[0].event());
 }
 
-TEST_P(UserActivityManagerTest, SuspendOther) {
+TEST_F(UserActivityManagerTest, SuspendOther) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -760,7 +689,7 @@
 }
 
 // Test feature extraction.
-TEST_P(UserActivityManagerTest, FeatureExtraction) {
+TEST_F(UserActivityManagerTest, FeatureExtraction) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -810,7 +739,7 @@
   EXPECT_FALSE(features.screen_locked_initially());
 }
 
-TEST_P(UserActivityManagerTest, ManagedDevice) {
+TEST_F(UserActivityManagerTest, ManagedDevice) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -827,7 +756,7 @@
   EXPECT_EQ(UserActivityEvent::Features::MANAGED, features.device_management());
 }
 
-TEST_P(UserActivityManagerTest, DimAndOffDelays) {
+TEST_F(UserActivityManagerTest, DimAndOffDelays) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -846,7 +775,7 @@
   EXPECT_EQ(1, features.dim_to_screen_off_sec());
 }
 
-TEST_P(UserActivityManagerTest, DimDelays) {
+TEST_F(UserActivityManagerTest, DimDelays) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -865,7 +794,7 @@
   EXPECT_TRUE(!features.has_dim_to_screen_off_sec());
 }
 
-TEST_P(UserActivityManagerTest, OffDelays) {
+TEST_F(UserActivityManagerTest, OffDelays) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -886,7 +815,7 @@
 
 // Screen is off when idle event is reported. No subsequent change in screen
 // state.
-TEST_P(UserActivityManagerTest, InitialScreenOff) {
+TEST_F(UserActivityManagerTest, InitialScreenOff) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -918,7 +847,7 @@
 
 // Screen is off when idle event is reported. No subsequent change in screen
 // state.
-TEST_P(UserActivityManagerTest, InitialScreenStateFlipped) {
+TEST_F(UserActivityManagerTest, InitialScreenStateFlipped) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -951,7 +880,7 @@
 
 // Screen is off when idle event is reported. No subsequent change in screen
 // state.
-TEST_P(UserActivityManagerTest, ScreenOffStateChanged) {
+TEST_F(UserActivityManagerTest, ScreenOffStateChanged) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -980,26 +909,18 @@
   EqualEvent(expected_event, events[0].event());
 }
 
-TEST_P(UserActivityManagerTest, ScreenDimDeferredWithFinalEvent) {
+TEST_F(UserActivityManagerTest, ScreenDimDeferredWithFinalEvent) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
       {"dim_threshold", "0.651"}};
   base::test::ScopedFeatureList scoped_feature_list;
-  if (use_new_ml_agent_) {
-    SmartDimMlAgent::GetInstance()->ResetForTesting();
-    scoped_feature_list.InitAndEnableFeatureWithParameters(
-        features::kUserActivityPrediction, params);
-  } else {
-    scoped_feature_list.InitWithFeaturesAndParameters(
-        {{features::kUserActivityPrediction, params}},
-        {features::kSmartDimNewMlAgent});
-  }
+  SmartDimMlAgent::GetInstance()->ResetForTesting();
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      features::kUserActivityPrediction, params);
 
   // sigmoid(0.43) * 100 = 60
   fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
                                           std::vector<double>{0.43});
-  model_.set_inactivity_score(60);
-  model_.set_decision_threshold(65);
 
   const IdleEventNotifier::ActivityData data;
   bool should_defer = false;
@@ -1010,10 +931,8 @@
 
   histogram_tester.ExpectTotalCount(
       "PowerML.SmartDimModel.RequestCompleteDuration", 1);
-
-  if (use_new_ml_agent_)
-    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
-                                       0, 1);
+  histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType", 0,
+                                     1);
 
   const std::vector<UserActivityEvent>& events = delegate_.events();
   ASSERT_EQ(1U, events.size());
@@ -1035,26 +954,18 @@
   EqualModelPrediction(expected_prediction, events[0].model_prediction());
 }
 
-TEST_P(UserActivityManagerTest, ScreenDimDeferredWithoutFinalEvent) {
+TEST_F(UserActivityManagerTest, ScreenDimDeferredWithoutFinalEvent) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
       {"dim_threshold", "0.651"}};
   base::test::ScopedFeatureList scoped_feature_list;
-  if (use_new_ml_agent_) {
-    SmartDimMlAgent::GetInstance()->ResetForTesting();
-    scoped_feature_list.InitAndEnableFeatureWithParameters(
-        features::kUserActivityPrediction, params);
-  } else {
-    scoped_feature_list.InitWithFeaturesAndParameters(
-        {{features::kUserActivityPrediction, params}},
-        {features::kSmartDimNewMlAgent});
-  }
+  SmartDimMlAgent::GetInstance()->ResetForTesting();
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      features::kUserActivityPrediction, params);
 
   // sigmoid(0.43) * 100 = 60
   fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
                                           std::vector<double>{0.43});
-  model_.set_inactivity_score(60);
-  model_.set_decision_threshold(65);
 
   const IdleEventNotifier::ActivityData data;
   bool should_defer = false;
@@ -1064,10 +975,8 @@
 
   histogram_tester.ExpectTotalCount(
       "PowerML.SmartDimModel.RequestCompleteDuration", 1);
-
-  if (use_new_ml_agent_)
-    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
-                                       0, 1);
+  histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType", 0,
+                                     1);
 
   const std::vector<UserActivityEvent>& events = delegate_.events();
   EXPECT_TRUE(events.empty());
@@ -1075,26 +984,18 @@
 
 // Tests the cancellation of a Smart Dim decision request, immediately after it
 // has been requested.
-TEST_P(UserActivityManagerTest, ScreenDimRequestCanceled) {
+TEST_F(UserActivityManagerTest, ScreenDimRequestCanceled) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
       {"dim_threshold", "0.651"}};
   base::test::ScopedFeatureList scoped_feature_list;
-  if (use_new_ml_agent_) {
-    SmartDimMlAgent::GetInstance()->ResetForTesting();
-    scoped_feature_list.InitAndEnableFeatureWithParameters(
-        features::kUserActivityPrediction, params);
-  } else {
-    scoped_feature_list.InitWithFeaturesAndParameters(
-        {{features::kUserActivityPrediction, params}},
-        {features::kSmartDimNewMlAgent});
-  }
+  SmartDimMlAgent::GetInstance()->ResetForTesting();
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      features::kUserActivityPrediction, params);
 
   // sigmoid(0.43) * 100 = 60
   fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
                                           std::vector<double>{0.43});
-  model_.set_inactivity_score(60);
-  model_.set_decision_threshold(65);
 
   const IdleEventNotifier::ActivityData data;
   bool should_defer = false;
@@ -1109,10 +1010,8 @@
       "PowerML.SmartDimModel.RequestCompleteDuration", 0);
   histogram_tester.ExpectTotalCount(
       "PowerML.SmartDimModel.RequestCanceledDuration", 1);
-
-  if (use_new_ml_agent_)
-    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
-                                       0, 1);
+  histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType", 0,
+                                     1);
 
   // Since the pending SmartDim decision request was canceled, we shouldn't
   // have any UserActivityEvent generated.
@@ -1122,26 +1021,18 @@
 
 // Tests the cancellation of a Smart Dim decision request, when two idle events
 // occur in quick succession. This verifies that only one request is serviced.
-TEST_P(UserActivityManagerTest, ScreenDimConsecutiveRequests) {
+TEST_F(UserActivityManagerTest, ScreenDimConsecutiveRequests) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
       {"dim_threshold", "0.651"}};
   base::test::ScopedFeatureList scoped_feature_list;
-  if (use_new_ml_agent_) {
-    SmartDimMlAgent::GetInstance()->ResetForTesting();
-    scoped_feature_list.InitAndEnableFeatureWithParameters(
-        features::kUserActivityPrediction, params);
-  } else {
-    scoped_feature_list.InitWithFeaturesAndParameters(
-        {{features::kUserActivityPrediction, params}},
-        {features::kSmartDimNewMlAgent});
-  }
+  SmartDimMlAgent::GetInstance()->ResetForTesting();
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      features::kUserActivityPrediction, params);
 
   // sigmoid(0.43) * 100 = 60
   fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
                                           std::vector<double>{0.43});
-  model_.set_inactivity_score(60);
-  model_.set_decision_threshold(65);
 
   const IdleEventNotifier::ActivityData data;
   bool should_defer_1 = false;
@@ -1156,10 +1047,8 @@
       "PowerML.SmartDimModel.RequestCompleteDuration", 1);
   histogram_tester.ExpectTotalCount(
       "PowerML.SmartDimModel.RequestCanceledDuration", 1);
-
-  if (use_new_ml_agent_)
-    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
-                                       0, 2);
+  histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType", 0,
+                                     2);
 
   const std::vector<UserActivityEvent>& events = delegate_.events();
   ASSERT_EQ(1U, events.size());
@@ -1181,26 +1070,18 @@
   EqualModelPrediction(expected_prediction, events[0].model_prediction());
 }
 
-TEST_P(UserActivityManagerTest, ScreenDimNotDeferred) {
+TEST_F(UserActivityManagerTest, ScreenDimNotDeferred) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
       {"dim_threshold", base::NumberToString(0.0)}};
   base::test::ScopedFeatureList scoped_feature_list;
-  if (use_new_ml_agent_) {
-    SmartDimMlAgent::GetInstance()->ResetForTesting();
-    scoped_feature_list.InitAndEnableFeatureWithParameters(
-        features::kUserActivityPrediction, params);
-  } else {
-    scoped_feature_list.InitWithFeaturesAndParameters(
-        {{features::kUserActivityPrediction, params}},
-        {features::kSmartDimNewMlAgent});
-  }
+  SmartDimMlAgent::GetInstance()->ResetForTesting();
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      features::kUserActivityPrediction, params);
 
   // sigmoid(0.43) * 100 = 60
   fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
                                           std::vector<double>{0.43});
-  model_.set_inactivity_score(60);
-  model_.set_decision_threshold(50);
 
   const IdleEventNotifier::ActivityData data;
   bool should_defer = false;
@@ -1211,10 +1092,8 @@
 
   histogram_tester.ExpectTotalCount(
       "PowerML.SmartDimModel.RequestCompleteDuration", 1);
-
-  if (use_new_ml_agent_)
-    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
-                                       0, 1);
+  histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType", 0,
+                                     1);
 
   const std::vector<UserActivityEvent>& events = delegate_.events();
   ASSERT_EQ(1U, events.size());
@@ -1228,27 +1107,19 @@
   EqualModelPrediction(expected_prediction, events[0].model_prediction());
 }
 
-TEST_P(UserActivityManagerTest, TwoScreenDimImminentWithEventInBetween) {
+TEST_F(UserActivityManagerTest, TwoScreenDimImminentWithEventInBetween) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
       {"dim_threshold", base::NumberToString(0.0)}};
   base::test::ScopedFeatureList scoped_feature_list;
-  if (use_new_ml_agent_) {
-    SmartDimMlAgent::GetInstance()->ResetForTesting();
-    scoped_feature_list.InitAndEnableFeatureWithParameters(
-        features::kUserActivityPrediction, params);
-  } else {
-    scoped_feature_list.InitWithFeaturesAndParameters(
-        {{features::kUserActivityPrediction, params}},
-        {features::kSmartDimNewMlAgent});
-  }
-  model_.set_decision_threshold(50);
+  SmartDimMlAgent::GetInstance()->ResetForTesting();
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      features::kUserActivityPrediction, params);
 
   // 1st ScreenDimImminent gets deferred
   // sigmoid(-0.4) * 100 = 40
   fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
                                           std::vector<double>{-0.4});
-  model_.set_inactivity_score(40);
 
   const IdleEventNotifier::ActivityData data;
   bool should_defer = false;
@@ -1264,7 +1135,6 @@
   // sigmoid(-1.35) * 100 = 20
   fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
                                           std::vector<double>{-1.35});
-  model_.set_inactivity_score(20);
   task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(10));
   ReportIdleEvent(data, &should_defer);
   task_environment()->RunUntilIdle();
@@ -1272,10 +1142,8 @@
 
   histogram_tester.ExpectTotalCount(
       "PowerML.SmartDimModel.RequestCompleteDuration", 2);
-
-  if (use_new_ml_agent_)
-    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
-                                       0, 2);
+  histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType", 0,
+                                     2);
 
   // Log when a SuspendImminent is received
   task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(20));
@@ -1321,27 +1189,19 @@
   EqualModelPrediction(expected_prediction2, events[1].model_prediction());
 }
 
-TEST_P(UserActivityManagerTest, TwoScreenDimImminentWithoutEventInBetween) {
+TEST_F(UserActivityManagerTest, TwoScreenDimImminentWithoutEventInBetween) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
       {"dim_threshold", base::NumberToString(0.0)}};
   base::test::ScopedFeatureList scoped_feature_list;
-  if (use_new_ml_agent_) {
-    SmartDimMlAgent::GetInstance()->ResetForTesting();
-    scoped_feature_list.InitAndEnableFeatureWithParameters(
-        features::kUserActivityPrediction, params);
-  } else {
-    scoped_feature_list.InitWithFeaturesAndParameters(
-        {{features::kUserActivityPrediction, params}},
-        {features::kSmartDimNewMlAgent});
-  }
-  model_.set_decision_threshold(50);
+  SmartDimMlAgent::GetInstance()->ResetForTesting();
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      features::kUserActivityPrediction, params);
 
   // 1st ScreenDimImminent gets deferred
   // sigmoid(-0.4) * 100 = 40
   fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
                                           std::vector<double>{-0.4});
-  model_.set_inactivity_score(40);
   const IdleEventNotifier::ActivityData data;
   bool should_defer = false;
   ReportIdleEvent(data, &should_defer);
@@ -1352,7 +1212,6 @@
   // sigmoid(-1.35) * 100 = 20
   fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
                                           std::vector<double>{-1.35});
-  model_.set_inactivity_score(20);
   task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(10));
   ReportIdleEvent(data, &should_defer);
   task_environment()->RunUntilIdle();
@@ -1360,10 +1219,8 @@
 
   histogram_tester.ExpectTotalCount(
       "PowerML.SmartDimModel.RequestCompleteDuration", 2);
-
-  if (use_new_ml_agent_)
-    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
-                                       0, 2);
+  histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType", 0,
+                                     2);
 
   // Log when a SuspendImminent is received
   task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(20));
@@ -1404,53 +1261,8 @@
   EqualModelPrediction(expected_prediction2, events[0].model_prediction());
 }
 
-TEST_P(UserActivityManagerTest, ModelError) {
-  base::HistogramTester histogram_tester;
-  const std::map<std::string, std::string> params = {
-      {"dim_threshold", "0.651"}};
-  base::test::ScopedFeatureList scoped_feature_list;
-  // This ModelError only happens in old SmartDimModel, not for new ml_agent.
-  // Now that the new ml_agent is the default behavior, we need to disable
-  // kSmartDimNewMlAgent for this test.
-  scoped_feature_list.InitWithFeaturesAndParameters(
-      {{features::kUserActivityPrediction, params}},
-      {features::kSmartDimNewMlAgent});
-
-  // This value will trigger a model error.
-  model_.set_inactivity_score(160);
-  model_.set_decision_threshold(65);
-
-  const IdleEventNotifier::ActivityData data;
-  bool should_defer = false;
-  ReportIdleEvent(data, &should_defer);
-  task_environment()->RunUntilIdle();
-  ReportUserActivity(nullptr);
-  EXPECT_FALSE(should_defer);
-
-  std::string histogram("PowerML.SmartDimModel.RequestCompleteDuration");
-  histogram_tester.ExpectTotalCount(histogram, 1);
-
-  const std::vector<UserActivityEvent>& events = delegate_.events();
-  ASSERT_EQ(1U, events.size());
-
-  UserActivityEvent::Event expected_event;
-  expected_event.set_type(UserActivityEvent::Event::REACTIVATE);
-  expected_event.set_reason(UserActivityEvent::Event::USER_ACTIVITY);
-  expected_event.set_log_duration_sec(0);
-  expected_event.set_screen_dim_occurred(false);
-  expected_event.set_screen_off_occurred(false);
-  expected_event.set_screen_lock_occurred(false);
-  EqualEvent(expected_event, events[0].event());
-
-  UserActivityEvent::ModelPrediction expected_prediction;
-  expected_prediction.set_model_applied(false);
-  expected_prediction.set_response(
-      UserActivityEvent::ModelPrediction::MODEL_ERROR);
-  EqualModelPrediction(expected_prediction, events[0].model_prediction());
-}
-
 // Test is flaky. See https://crbug.com/938055.
-TEST_P(UserActivityManagerTest, DISABLED_BasicTabs) {
+TEST_F(UserActivityManagerTest, DISABLED_BasicTabs) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -1482,7 +1294,7 @@
 }
 
 // Test is flaky. See https://crbug.com/938141.
-TEST_P(UserActivityManagerTest, DISABLED_MultiBrowsersAndTabs) {
+TEST_F(UserActivityManagerTest, DISABLED_MultiBrowsersAndTabs) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -1529,7 +1341,7 @@
   tab_strip_model3->CloseAllTabs();
 }
 
-TEST_P(UserActivityManagerTest, Incognito) {
+TEST_F(UserActivityManagerTest, Incognito) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -1557,7 +1369,7 @@
   tab_strip_model->CloseAllTabs();
 }
 
-TEST_P(UserActivityManagerTest, NoOpenTabs) {
+TEST_F(UserActivityManagerTest, NoOpenTabs) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -1578,10 +1390,6 @@
   EXPECT_FALSE(features.has_has_form_entry());
 }
 
-INSTANTIATE_TEST_SUITE_P(UserActivityManagerTestInstantiation,
-                         UserActivityManagerTest,
-                         testing::Values(false, true));
-
 }  // namespace ml
 }  // namespace power
 }  // namespace chromeos
diff --git a/chrome/browser/data_saver/lite_video_browsertest.cc b/chrome/browser/data_saver/lite_video_browsertest.cc
index a409f1e..5020cd55 100644
--- a/chrome/browser/data_saver/lite_video_browsertest.cc
+++ b/chrome/browser/data_saver/lite_video_browsertest.cc
@@ -350,10 +350,6 @@
   ukm_recorder.ExpectEntryMetric(
       entry, ukm::builders::LiteVideo::kBlocklistReasonName,
       static_cast<int>(lite_video::LiteVideoBlocklistReason::kUnknown));
-  ukm_recorder.ExpectEntryMetric(
-      entry, ukm::builders::LiteVideo::kThrottlingResultName,
-      static_cast<int>(
-          lite_video::LiteVideoThrottleResult::kThrottledWithoutStop));
 }
 
 class LiteVideoAndLiteModeDisabledBrowserTest : public LiteVideoBrowserTest {
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc
index 5753ac4..3af98c0b 100644
--- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc
@@ -311,6 +311,23 @@
       EXPECT_EQ(*expected_rules_count, actual_rules_count);
   }
 
+  void VerifyGetAvailableStaticRuleCountFunction(
+      const Extension& extension,
+      size_t expected_available_rule_count) {
+    auto function = base::MakeRefCounted<
+        DeclarativeNetRequestGetAvailableStaticRuleCountFunction>();
+    function->set_extension(&extension);
+    function->set_has_callback(true);
+
+    std::unique_ptr<base::Value> result =
+        api_test_utils::RunFunctionAndReturnSingleResult(
+            function.get(), "[]" /* args */, browser_context());
+    ASSERT_TRUE(result);
+
+    EXPECT_EQ(expected_available_rule_count,
+              static_cast<size_t>(result->GetInt()));
+  }
+
   const ExtensionPrefs* extension_prefs() { return extension_prefs_; }
 
   ChromeTestExtensionLoader* extension_loader() { return loader_.get(); }
@@ -2005,6 +2022,81 @@
   CheckExtensionAllocationInPrefs(extension()->id(), 200);
 }
 
+// Test that getAvailableStaticRuleCount returns the correct number of rules an
+// extension can still enable.
+TEST_P(MultipleRulesetsGlobalRulesTest, GetAvailableStaticRuleCount) {
+  // Override the API guaranteed minimum to prevent a timeout on loading the
+  // extension.
+  base::AutoReset<int> guaranteed_minimum_override =
+      CreateScopedStaticGuaranteedMinimumOverrideForTesting(100);
+
+  // Similarly, override the global limit to prevent a timeout.
+  base::AutoReset<int> global_limit_override =
+      CreateScopedGlobalStaticRuleLimitOverrideForTesting(200);
+
+  ASSERT_EQ(300, GetStaticRuleLimit());
+
+  AddRuleset(CreateRuleset(kId1, 50, 0, true));
+  AddRuleset(CreateRuleset(kId2, 100, 0, false));
+
+  RulesetManagerObserver ruleset_waiter(manager());
+
+  LoadAndExpectSuccess(150, 50);
+
+  ruleset_waiter.WaitForExtensionsWithRulesetsCount(1);
+  scoped_refptr<const Extension> first_extension = extension();
+  ASSERT_TRUE(first_extension.get());
+  ExtensionId first_extension_id = first_extension.get()->id();
+
+  // Initially, the extension should have 250 more static rules available, and
+  // no rules allocated from the global pool.
+  VerifyPublicRulesetIDs(*first_extension.get(), {kId1});
+  CheckExtensionAllocationInPrefs(first_extension_id, base::nullopt);
+  VerifyGetAvailableStaticRuleCountFunction(*first_extension.get(), 250);
+
+  // Enabling |kId2| should result in 50 rules allocated in the global pool, and
+  // 150 more rules available for the extension to enable.
+  RunUpdateEnabledRulesetsFunction(*first_extension.get(), {}, {kId2},
+                                   base::nullopt /* expected_error */);
+  VerifyPublicRulesetIDs(*first_extension.get(), {kId1, kId2});
+  CheckExtensionAllocationInPrefs(first_extension_id, 50);
+  VerifyGetAvailableStaticRuleCountFunction(*first_extension.get(), 150);
+
+  // Disabling all rulesets should result in 300 rules available.
+  RunUpdateEnabledRulesetsFunction(*first_extension.get(), {kId1, kId2}, {},
+                                   base::nullopt /* expected_error */);
+  VerifyPublicRulesetIDs(*first_extension.get(), {});
+  CheckExtensionAllocationInPrefs(first_extension_id, base::nullopt);
+  VerifyGetAvailableStaticRuleCountFunction(*first_extension.get(), 300);
+
+  // Load another extension with one ruleset with 300 rules.
+  UpdateExtensionLoaderAndPath(
+      temp_dir().GetPath().Append(FILE_PATH_LITERAL("test_extension_2")));
+  ClearRulesets();
+
+  AddRuleset(CreateRuleset(kId3, GetStaticRuleLimit(), 0, true));
+  DeclarativeNetRequestUnittest::LoadAndExpectSuccess(
+      GetStaticRuleLimit(), GetStaticRuleLimit(),
+      true /* expect_rulesets_indexed */);
+
+  ruleset_waiter.WaitForExtensionsWithRulesetsCount(2);
+  scoped_refptr<const Extension> second_extension = extension();
+  ASSERT_TRUE(second_extension.get());
+  ExtensionId second_extension_id = second_extension.get()->id();
+
+  VerifyPublicRulesetIDs(*second_extension.get(), {kId3});
+  CheckExtensionAllocationInPrefs(second_extension_id, 200);
+
+  // The first extension should still have GetStaticGuaranteedMinimumRuleCount()
+  // rules available as it has no rules enabled and the global pool is full.
+  VerifyGetAvailableStaticRuleCountFunction(
+      *first_extension.get(), GetStaticGuaranteedMinimumRuleCount());
+
+  // The second extension should not have any rules available since its
+  // allocation consists of the entire global pool.
+  VerifyGetAvailableStaticRuleCountFunction(*second_extension.get(), 0);
+}
+
 INSTANTIATE_TEST_SUITE_P(All,
                          SingleRulesetTest,
                          ::testing::Values(ExtensionLoadType::PACKED,
diff --git a/chrome/browser/extensions/isolated_world_csp_browsertest.cc b/chrome/browser/extensions/isolated_world_csp_browsertest.cc
new file mode 100644
index 0000000..5da83d39
--- /dev/null
+++ b/chrome/browser/extensions/isolated_world_csp_browsertest.cc
@@ -0,0 +1,105 @@
+// 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 "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/dns/mock_host_resolver.h"
+
+namespace extensions {
+
+class IsolatedWorldCspBrowserTest : public ExtensionApiTest {
+ public:
+  // ExtensionApiTest override.
+  void SetUpOnMainThread() override {
+    extensions::ExtensionApiTest::SetUpOnMainThread();
+
+    // Override the path used for loading the extension.
+    test_data_dir_ = test_data_dir_.AppendASCII("isolated_world_csp");
+
+    embedded_test_server()->ServeFilesFromDirectory(test_data_dir_);
+    ASSERT_TRUE(StartEmbeddedTestServer());
+
+    // Map all hosts to localhost.
+    host_resolver()->AddRule("*", "127.0.0.1");
+  }
+};
+
+// Test that a Manifest V2 content script can use eval by bypassing the main
+// world CSP.
+IN_PROC_BROWSER_TEST_F(IsolatedWorldCspBrowserTest, Eval_ManifestV2) {
+  GURL url = embedded_test_server()->GetURL("eval.com",
+                                            "/page_with_script_src_csp.html");
+  ASSERT_TRUE(RunExtensionSubtest("mv2", url.spec())) << message_;
+}
+
+// Test that a Manifest V3 content script can't use eval.
+IN_PROC_BROWSER_TEST_F(IsolatedWorldCspBrowserTest, Eval_ManifestV3) {
+  // TODO(crbug.com/896897): Ignore manifest warnings for now since we get a
+  // warning for using manifest version 3.
+  GURL url = embedded_test_server()->GetURL("eval.com",
+                                            "/page_with_script_src_csp.html");
+  ASSERT_TRUE(RunExtensionSubtest("mv3", url.spec(),
+                                  kFlagIgnoreManifestWarnings, kFlagNone))
+      << message_;
+}
+
+// Test that a Manifest V2 content script can navigate to a javascript url by
+// bypassing the main world CSP.
+IN_PROC_BROWSER_TEST_F(IsolatedWorldCspBrowserTest, JavascriptUrl_ManifestV2) {
+  GURL url = embedded_test_server()->GetURL("js-url.com",
+                                            "/page_with_script_src_csp.html");
+  ASSERT_TRUE(RunExtensionSubtest("mv2", url.spec())) << message_;
+}
+
+// Test that a Manifest V3 content script can't navigate to a javascript url
+// while in its isolated world.
+IN_PROC_BROWSER_TEST_F(IsolatedWorldCspBrowserTest, JavascriptUrl_ManifestV3) {
+  // We wait on a console message which will be raised on an unsuccessful
+  // navigation to a javascript url since there isn't any other clean way to
+  // assert that the navigation didn't succeed.
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  content::WebContentsConsoleObserver console_observer(web_contents);
+  console_observer.SetPattern(
+      "Refused to run the JavaScript URL because it violates the following "
+      "Content Security Policy directive: \"script-src 'self'\".*");
+
+  // TODO(crbug.com/896897): Ignore manifest warnings for now since we get a
+  // warning for using manifest version 3.
+  GURL url = embedded_test_server()->GetURL("js-url.com",
+                                            "/page_with_script_src_csp.html");
+  ASSERT_TRUE(RunExtensionSubtest("mv3", url.spec(),
+                                  kFlagIgnoreManifestWarnings, kFlagNone))
+      << message_;
+  console_observer.Wait();
+
+  // Also ensure the page title wasn't changed.
+  EXPECT_EQ(base::ASCIIToUTF16("Page With CSP"), web_contents->GetTitle());
+}
+
+// Test that a Manifest V2 content script can execute a remote script even if
+// it is disallowed by the main world CSP.
+IN_PROC_BROWSER_TEST_F(IsolatedWorldCspBrowserTest,
+                       RemoteScriptSrc_ManifestV2) {
+  GURL url = embedded_test_server()->GetURL("remote-script.com",
+                                            "/page_with_script_src_csp.html");
+  ASSERT_TRUE(RunExtensionSubtest("mv2", url.spec())) << message_;
+}
+
+// Test that a Manifest V3 content script can't execute a remote script even if
+// is allowed by the main world CSP.
+IN_PROC_BROWSER_TEST_F(IsolatedWorldCspBrowserTest,
+                       RemoteScriptSrc_ManifestV3) {
+  // TODO(crbug.com/896897): Ignore manifest warnings for now since we get a
+  // warning for using manifest version 3.
+  GURL url = embedded_test_server()->GetURL("remote-script.com",
+                                            "/page_with_script_src_csp.html");
+  ASSERT_TRUE(RunExtensionSubtest("mv3", url.spec(),
+                                  kFlagIgnoreManifestWarnings, kFlagNone))
+      << message_;
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 3039bb4d..cd442cb 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -3720,12 +3720,12 @@
   {
     "name": "pluginvm-show-camera-permissions",
     "owners": [ "danielng@google.com", "lxj@google.com" ],
-    "expiry_milestone": 87
+    "expiry_milestone": 90
   },
   {
     "name": "pluginvm-show-microphone-permissions",
     "owners": [ "dtor", "lxj@google.com" ],
-    "expiry_milestone": 87
+    "expiry_milestone": 90
   },
   {
     "name": "pointer-support",
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 7ef9e6a4..55e5df3 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -190,7 +190,6 @@
     &kSharedClipboardUI,
     &kSharingQrCodeAndroid,
     &kShoppingAssist,
-    &kSigninPromoMaxImpressionsAndroid,
     &kSpannableInlineAutocomplete,
     &kSpecialLocaleWrapper,
     &kSpecialUserDecision,
@@ -559,9 +558,6 @@
 const base::Feature kShoppingAssist{"ShoppingAssist",
                                     base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature kSigninPromoMaxImpressionsAndroid{
-    "SigninPromoMaxImpressionsAndroid", base::FEATURE_DISABLED_BY_DEFAULT};
-
 const base::Feature kSpannableInlineAutocomplete{
     "SpannableInlineAutocomplete", base::FEATURE_ENABLED_BY_DEFAULT};
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h
index a2a391e..2bc1cd3f 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -104,7 +104,6 @@
 extern const base::Feature kShareButtonInTopToolbar;
 extern const base::Feature kShareByDefaultInCCT;
 extern const base::Feature kShoppingAssist;
-extern const base::Feature kSigninPromoMaxImpressionsAndroid;
 extern const base::Feature kSpannableInlineAutocomplete;
 extern const base::Feature kSpecialLocaleWrapper;
 extern const base::Feature kSpecialUserDecision;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index ee2a705..e06247c 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -398,8 +398,6 @@
     public static final String SHARED_CLIPBOARD_UI = "SharedClipboardUI";
     public static final String SHARING_QR_CODE_ANDROID = "SharingQrCodeAndroid";
     public static final String SHOW_TRUSTED_PUBLISHER_URL = "ShowTrustedPublisherURL";
-    public static final String SIGNIN_PROMO_MAX_IMPRESSIONS_ANDROID =
-            "SigninPromoMaxImpressionsAndroid";
     public static final String SMART_SUGGESTION_FOR_LARGE_DOWNLOADS =
             "SmartSuggestionForLargeDownloads";
     public static final String SPANNABLE_INLINE_AUTOCOMPLETE = "SpannableInlineAutocomplete";
diff --git a/chrome/browser/media/unified_autoplay_config_unittest.cc b/chrome/browser/media/unified_autoplay_config_unittest.cc
index 4632eed8..c0c5afe9 100644
--- a/chrome/browser/media/unified_autoplay_config_unittest.cc
+++ b/chrome/browser/media/unified_autoplay_config_unittest.cc
@@ -16,6 +16,7 @@
 #include "content/public/test/web_contents_tester.h"
 #include "media/base/media_switches.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
+#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h"
 
 // Unit tests for the unified autoplay policy with the unified sound settings
 // UI enabled.
@@ -50,7 +51,7 @@
     return UnifiedAutoplayConfig::ShouldBlockAutoplay(profile());
   }
 
-  blink::web_pref::AutoplayPolicy GetAppliedAutoplayPolicy() {
+  blink::mojom::AutoplayPolicy GetAppliedAutoplayPolicy() {
     return web_contents()->GetOrCreateWebPreferences().autoplay_policy;
   }
 
@@ -72,7 +73,7 @@
   EXPECT_FALSE(ShouldBlockAutoplay());
 
   NavigateToTestPage();
-  EXPECT_EQ(blink::web_pref::AutoplayPolicy::kNoUserGestureRequired,
+  EXPECT_EQ(blink::mojom::AutoplayPolicy::kNoUserGestureRequired,
             GetAppliedAutoplayPolicy());
 }
 
@@ -83,7 +84,7 @@
   EXPECT_TRUE(ShouldBlockAutoplay());
 
   NavigateToTestPage();
-  EXPECT_EQ(blink::web_pref::AutoplayPolicy::kDocumentUserActivationRequired,
+  EXPECT_EQ(blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired,
             GetAppliedAutoplayPolicy());
 
   // Set back to ALLOW to ensure that the policy is updated on the next
@@ -92,7 +93,7 @@
   EXPECT_FALSE(ShouldBlockAutoplay());
 
   NavigateToTestPage();
-  EXPECT_EQ(blink::web_pref::AutoplayPolicy::kNoUserGestureRequired,
+  EXPECT_EQ(blink::mojom::AutoplayPolicy::kNoUserGestureRequired,
             GetAppliedAutoplayPolicy());
 }
 
@@ -106,7 +107,7 @@
   EXPECT_FALSE(ShouldBlockAutoplay());
 
   NavigateToTestPage();
-  EXPECT_EQ(blink::web_pref::AutoplayPolicy::kDocumentUserActivationRequired,
+  EXPECT_EQ(blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired,
             GetAppliedAutoplayPolicy());
 }
 
@@ -114,7 +115,7 @@
   EXPECT_TRUE(ShouldBlockAutoplay());
 
   NavigateToTestPage();
-  EXPECT_EQ(blink::web_pref::AutoplayPolicy::kDocumentUserActivationRequired,
+  EXPECT_EQ(blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired,
             GetAppliedAutoplayPolicy());
 }
 
@@ -123,7 +124,7 @@
   EXPECT_FALSE(ShouldBlockAutoplay());
 
   NavigateToTestPage();
-  EXPECT_EQ(blink::web_pref::AutoplayPolicy::kNoUserGestureRequired,
+  EXPECT_EQ(blink::mojom::AutoplayPolicy::kNoUserGestureRequired,
             GetAppliedAutoplayPolicy());
 
   // Now update the pref and make sure we apply it on the next navigation.
@@ -131,7 +132,7 @@
   EXPECT_TRUE(ShouldBlockAutoplay());
 
   NavigateToTestPage();
-  EXPECT_EQ(blink::web_pref::AutoplayPolicy::kDocumentUserActivationRequired,
+  EXPECT_EQ(blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired,
             GetAppliedAutoplayPolicy());
 }
 
@@ -159,6 +160,6 @@
   EXPECT_TRUE(ShouldBlockAutoplay());
 
   NavigateToTestPage();
-  EXPECT_EQ(blink::web_pref::AutoplayPolicy::kUserGestureRequired,
+  EXPECT_EQ(blink::mojom::AutoplayPolicy::kUserGestureRequired,
             GetAppliedAutoplayPolicy());
 }
diff --git a/chrome/browser/notifications/notification_platform_bridge_lacros.cc b/chrome/browser/notifications/notification_platform_bridge_lacros.cc
index 4116a613..36fcdd1 100644
--- a/chrome/browser/notifications/notification_platform_bridge_lacros.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_lacros.cc
@@ -12,8 +12,6 @@
 #include "base/numerics/safe_conversions.h"
 #include "base/optional.h"
 #include "chrome/browser/notifications/notification_platform_bridge_delegate.h"
-#include "chromeos/crosapi/cpp/bitmap.h"
-#include "chromeos/crosapi/cpp/bitmap_util.h"
 #include "chromeos/crosapi/mojom/message_center.mojom.h"
 #include "chromeos/crosapi/mojom/notification.mojom.h"
 #include "ui/message_center/public/cpp/notification.h"
@@ -59,30 +57,15 @@
   mojo_note->message = notification.message();
   mojo_note->display_source = notification.display_source();
   mojo_note->origin_url = notification.origin_url();
-  if (!notification.icon().IsEmpty()) {
-    // TODO(https://crbug.com/1123969): Don't send the deprecated field after
-    // ash M87 beta.
-    SkBitmap icon = notification.icon().AsBitmap();
-    mojo_note->deprecated_icon = crosapi::BitmapFromSkBitmap(icon);
+  if (!notification.icon().IsEmpty())
     mojo_note->icon = notification.icon().AsImageSkia();
-  }
   mojo_note->priority = base::ClampToRange(notification.priority(), -2, 2);
   mojo_note->require_interaction = notification.never_timeout();
   mojo_note->timestamp = notification.timestamp();
-  if (!notification.image().IsEmpty()) {
-    // TODO(https://crbug.com/1123969): Don't send the deprecated field after
-    // ash M87 beta.
-    SkBitmap image = notification.image().AsBitmap();
-    mojo_note->deprecated_image = crosapi::BitmapFromSkBitmap(image);
+  if (!notification.image().IsEmpty())
     mojo_note->image = notification.image().AsImageSkia();
-  }
-  if (!notification.small_image().IsEmpty()) {
-    // TODO(https://crbug.com/1123969): Don't send the deprecated field after
-    // ash M87 beta.
-    SkBitmap badge = notification.small_image().AsBitmap();
-    mojo_note->deprecated_badge = crosapi::BitmapFromSkBitmap(badge);
+  if (!notification.small_image().IsEmpty())
     mojo_note->badge = notification.small_image().AsImageSkia();
-  }
   for (const auto& item : notification.items()) {
     auto mojo_item = crosapi::mojom::NotificationItem::New();
     mojo_item->title = item.title;
diff --git a/chrome/browser/notifications/notification_platform_bridge_lacros_unittest.cc b/chrome/browser/notifications/notification_platform_bridge_lacros_unittest.cc
index bae91f3b..00a9e30a 100644
--- a/chrome/browser/notifications/notification_platform_bridge_lacros_unittest.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_lacros_unittest.cc
@@ -7,8 +7,6 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/notifications/notification_platform_bridge_delegate.h"
-#include "chromeos/crosapi/cpp/bitmap.h"
-#include "chromeos/crosapi/cpp/bitmap_util.h"
 #include "chromeos/crosapi/mojom/message_center.mojom.h"
 #include "chromeos/crosapi/mojom/notification.mojom.h"
 #include "content/public/test/browser_task_environment.h"
@@ -178,17 +176,6 @@
   EXPECT_EQ(crosapi::mojom::FullscreenVisibility::kOverUser,
             last_notification->fullscreen_visibility);
 
-  // TODO(https://crbug.com/1123969): Don't test the deprecated field after
-  // ash M87 beta.
-  ASSERT_TRUE(last_notification->deprecated_badge.has_value());
-  EXPECT_TRUE(AreBitmapsEqual(
-      badge.AsBitmap(),
-      crosapi::SkBitmapFromBitmap(*last_notification->deprecated_badge)));
-  ASSERT_TRUE(last_notification->deprecated_icon.has_value());
-  EXPECT_TRUE(AreBitmapsEqual(
-      icon.AsBitmap(),
-      crosapi::SkBitmapFromBitmap(*last_notification->deprecated_icon)));
-
   ASSERT_FALSE(last_notification->badge.isNull());
   EXPECT_TRUE(last_notification->badge.HasRepresentation(1.0f));
   EXPECT_TRUE(last_notification->badge.HasRepresentation(2.0f));
@@ -223,12 +210,6 @@
   crosapi::mojom::Notification* last_notification =
       test_message_center_.last_notification_.get();
   ASSERT_TRUE(last_notification);
-  // TODO(https://crbug.com/1123969): Don't test the deprecated field after
-  // ash M87 beta.
-  ASSERT_TRUE(last_notification->deprecated_image.has_value());
-  EXPECT_TRUE(AreBitmapsEqual(
-      image.AsBitmap(),
-      crosapi::SkBitmapFromBitmap(*last_notification->deprecated_image)));
   ASSERT_FALSE(last_notification->image.isNull());
   EXPECT_TRUE(AreImagesEqual(image, gfx::Image(last_notification->image)));
 }
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index 11f49b2b..2de2d11 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -548,21 +548,19 @@
     grit_flags = [
       "-E",
       "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+      "-E",
+      "root_src_dir=" + rebase_path("//", root_build_dir),
     ]
 
     defines = chrome_grit_defines
-    if (optimize_webui) {
-      source = "extensions/extensions_resources_vulcanized.grd"
-      deps = [ "//chrome/browser/resources/extensions:build" ]
-    } else {
-      # These arguments are needed since the grd is generated at build time.
-      enable_input_discovery_for_gn_analyze = false
-      defines += [ "SHARED_INTERMEDIATE_DIR=" +
-                   rebase_path(root_gen_dir, root_build_dir) ]
-      extensions_gen_dir = "$root_gen_dir/chrome/browser/resources/extensions"
-      source = "$extensions_gen_dir/extensions_resources.grd"
-      deps = [ "//chrome/browser/resources/extensions:build_grd" ]
-    }
+
+    # These arguments are needed since the grd is generated at build time.
+    enable_input_discovery_for_gn_analyze = false
+    defines += [ "SHARED_INTERMEDIATE_DIR=" +
+                 rebase_path(root_gen_dir, root_build_dir) ]
+    extensions_gen_dir = "$root_gen_dir/chrome/browser/resources/extensions"
+    source = "$extensions_gen_dir/extensions_resources.grd"
+    deps = [ "//chrome/browser/resources/extensions:build_grd" ]
 
     outputs = [
       "grit/extensions_resources.h",
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn
index 5b9c4fb..effd165 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn
@@ -60,6 +60,7 @@
   sources = [
     "accessibility_common_test.js",
     "autoclick/autoclick_test.js",
+    "magnifier/magnifier_test.js",
   ]
   gen_include_files = [
     "../common/rect_util.js",
@@ -88,6 +89,7 @@
   deps = [
     ":autoclick",
     ":magnifier",
+    "../common:event_handler",
     "../common:instance_checker",
   ]
   externs_list = [
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_loader.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_loader.js
index 46f1fb7..440dbdb 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_loader.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_loader.js
@@ -71,6 +71,7 @@
     if (details.value && !this.magnifier_) {
       this.magnifier_ = new Magnifier();
     } else if (!details.value && this.magnifier_) {
+      this.magnifier_.onMagnifierDisabled();
       this.magnifier_ = null;
     }
   }
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick_test.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick_test.js
index c5b8ef1..4f275622 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick_test.js
@@ -62,9 +62,8 @@
 
 TEST_F('AutoclickE2ETest', 'HighlightsRootWebAreaIfNotScrollable', function() {
   this.runWithLoadedTree(
-      'data:text/html;charset=utf-8,<p>Cats rock!</p>',
-      async function(desktop) {
-        const node = desktop.find(
+      'data:text/html;charset=utf-8,<p>Cats rock!</p>', async function(root) {
+        const node = root.find(
             {role: RoleType.STATIC_TEXT, attributes: {name: 'Cats rock!'}});
         await new Promise(resolve => {
           this.mockAccessibilityPrivate.callOnScrollableBoundsForPointRequested(
@@ -86,8 +85,8 @@
           '<div style="width:100px;height:100px;overflow:scroll">' +
           '<div style="margin:50px">cats rock! this text wraps and overflows!' +
           '</div></div>',
-      async function(desktop) {
-        const node = desktop.find({
+      async function(root) {
+        const node = root.find({
           role: RoleType.STATIC_TEXT,
           attributes: {name: 'cats rock! this text wraps and overflows!'}
         });
@@ -110,8 +109,7 @@
 
 TEST_F('AutoclickE2ETest', 'RemovesAndAddsAutoclick', function() {
   this.runWithLoadedTree(
-      'data:text/html;charset=utf-8,<p>Cats rock!</p>',
-      async function(desktop) {
+      'data:text/html;charset=utf-8,<p>Cats rock!</p>', async function(root) {
         // Turn on screen magnifier so that when we turn off autoclick, the
         // extension doesn't get unloaded and crash the test.
         await new Promise(resolve => {
@@ -126,7 +124,7 @@
         await new Promise(resolve => {
           chrome.accessibilityFeatures.autoclick.set({value: true}, resolve);
         });
-        const node = desktop.find(
+        const node = root.find(
             {role: RoleType.STATIC_TEXT, attributes: {name: 'Cats rock!'}});
         await new Promise(resolve => {
           this.mockAccessibilityPrivate.callOnScrollableBoundsForPointRequested(
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js
index 7708c07..b69ab1cd 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js
@@ -6,5 +6,48 @@
  * Main class for the Chrome OS magnifier.
  */
 class Magnifier {
-  constructor() {}
+  constructor() {
+    /** @private {!EventHandler} */
+    this.activeDescendantHandler_ = new EventHandler(
+        [], chrome.automation.EventType.ACTIVE_DESCENDANT_CHANGED,
+        this.onActiveDescendantChanged_.bind(this));
+
+    this.init_();
+  }
+
+  /** Destructor to remove listener. */
+  onMagnifierDisabled() {
+    this.activeDescendantHandler_.stop();
+  }
+
+  /**
+   * Initializes Magnifier.
+   * @private
+   */
+  init_() {
+    chrome.automation.getDesktop(desktop => {
+      this.activeDescendantHandler_.setNodes(desktop);
+      this.activeDescendantHandler_.start();
+    });
+  }
+
+  /**
+   * Listener for when active descendant is changed. Moves magnifier to include
+   * active descendant in viewport.
+   * @param {!chrome.automation.AutomationEvent} event
+   * @private
+   */
+  onActiveDescendantChanged_(event) {
+    const {activeDescendant} = event.target;
+    if (!activeDescendant) {
+      return;
+    }
+
+    const {location} = activeDescendant;
+    if (!location) {
+      return;
+    }
+
+    chrome.accessibilityPrivate.moveMagnifierToRect(location);
+  }
 }
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier_test.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier_test.js
new file mode 100644
index 0000000..3a638c8
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier_test.js
@@ -0,0 +1,77 @@
+// 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.
+
+GEN_INCLUDE(['../../common/testing/e2e_test_base.js']);
+GEN_INCLUDE(['../../common/testing/mock_accessibility_private.js']);
+GEN_INCLUDE(['../../common/rect_util.js']);
+
+/**
+ * Magnifier feature using accessibility common extension browser tests.
+ */
+MagnifierE2ETest = class extends E2ETestBase {
+  constructor() {
+    super();
+    this.mockAccessibilityPrivate = MockAccessibilityPrivate;
+    chrome.accessibilityPrivate = this.mockAccessibilityPrivate;
+
+    window.RoleType = chrome.automation.RoleType;
+
+    // Re-initialize AccessibilityCommon with mock AccessibilityPrivate API.
+    window.accessibilityCommon = new AccessibilityCommon();
+  }
+
+  /** @override */
+  testGenCppIncludes() {
+    super.testGenCppIncludes();
+    GEN(`
+#include "chrome/browser/chromeos/accessibility/magnification_manager.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "content/public/test/browser_test.h"
+    `);
+  }
+
+  /** @override */
+  testGenPreamble() {
+    super.testGenPreamble();
+    GEN(`
+    base::Closure load_cb =
+        base::Bind(&chromeos::MagnificationManager::SetMagnifierEnabled,
+            base::Unretained(chromeos::MagnificationManager::Get()),
+            true);
+    WaitForExtension(extension_misc::kAccessibilityCommonExtensionId, load_cb);
+      `);
+  }
+};
+
+TEST_F(
+    'MagnifierE2ETest', 'MovesScreenMagnifierToActiveDescendant', function() {
+      const site = `
+    <div role="group" id="parent" aria-activedescendant="apple">
+      <div id="apple" role="treeitem">Apple</div>
+      <div id="banana" role="treeitem">Banana</div>
+    </div>
+    <script>
+      const parent = document.getElementById('parent');
+      parent.addEventListener('click', function() {
+        parent.setAttribute('aria-activedescendant', 'banana');
+      });
+      </script>
+  `;
+      this.runWithLoadedTree(site, async function(root) {
+        // Click parent to change active descendant from apple to banana.
+        const parent = root.find({role: RoleType.GROUP});
+        parent.doDefault();
+
+        // Register and wait for rect from magnifier.
+        const rect = await new Promise(resolve => {
+          this.mockAccessibilityPrivate.registerMoveMagnifierToRectCallback(
+              resolve);
+        });
+
+        // Validate rect from magnifier is rect of banana.
+        const bananaNode =
+            root.find({role: RoleType.TREE_ITEM, attributes: {name: 'Banana'}});
+        assertTrue(RectUtil.equal(rect, bananaNode.location));
+      }, {returnPage: true});
+    });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/testing/chromevox_next_e2e_test_base.js b/chrome/browser/resources/chromeos/accessibility/chromevox/testing/chromevox_next_e2e_test_base.js
index 954c1f3..eb2a6ba 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/testing/chromevox_next_e2e_test_base.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/testing/chromevox_next_e2e_test_base.js
@@ -89,10 +89,6 @@
 
   /** @override */
   runWithLoadedTree(doc, callback, opt_params = {}) {
-    if (opt_params.returnPage === undefined) {
-      opt_params.returnPage = true;
-    }
-
     callback = this.newCallback(callback);
     const wrappedCallback = (node) => {
       CommandHandler.onCommand('nextObject');
diff --git a/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler_test.js b/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler_test.js
index 982dc2b..25e3bb4 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler_test.js
@@ -14,7 +14,7 @@
 TEST_F(
     'RepeatedTreeChangeHandlerTest', 'RepeatedTreeChangeHandledOnce',
     function() {
-      this.runWithLoadedTree('', (root) => {
+      this.runWithLoadedDesktop(() => {
         this.handlerCallCount = 0;
         const handler = () => this.handlerCallCount++;
 
@@ -34,7 +34,7 @@
     });
 
 TEST_F('RepeatedTreeChangeHandlerTest', 'Predicate', function() {
-  this.runWithLoadedTree('', (root) => {
+  this.runWithLoadedDesktop(() => {
     this.handlerCallCount = 0;
     const handler = () => this.handlerCallCount++;
 
diff --git a/chrome/browser/resources/chromeos/accessibility/common/testing/e2e_test_base.js b/chrome/browser/resources/chromeos/accessibility/common/testing/e2e_test_base.js
index f4327376..a835bec 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/testing/e2e_test_base.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/testing/e2e_test_base.js
@@ -84,21 +84,32 @@
   }
 
   /**
+   * Gets the desktop from the automation API and runs |callback|.
+   * Arranges to call |testDone()| after |callback| returns.
+   * NOTE: Callbacks created inside |opt_callback| must be wrapped with
+   * |this.newCallback| if passed to asynchronous calls.  Otherwise, the test
+   * will be finished prematurely.
+   * @param {function(chrome.automation.AutomationNode)} callback
+   *     Called with the desktop node once it's retrieved.
+   */
+  runWithLoadedDesktop(callback) {
+    chrome.automation.getDesktop(this.newCallback(callback));
+  }
+
+  /**
    * Gets the desktop from the automation API and Launches a new tab with
    * the given document, and runs |callback| when a load complete fires.
    * Arranges to call |testDone()| after |callback| returns.
-   * NOTE: Callbacks created inside |opt_callback| must be wrapped with
+   * NOTE: Callbacks created inside |callback| must be wrapped with
    * |this.newCallback| if passed to asynchronous calls.  Otherwise, the test
    * will be finished prematurely.
    * @param {string|function(): string} doc An HTML snippet, optionally wrapped
    *     inside of a function.
    * @param {function(chrome.automation.AutomationNode)} callback
-   *     Called once the document is ready.
-   * @param {{url: (string=), returnPage: (boolean=)}}
+   *     Called with the root web area node once the document is ready.
+   * @param {{url: (string=), returnDesktop: (boolean=)}}
    *     opt_params
    *           url Optional url to wait for. Defaults to undefined.
-   *           returnPage True if the node for the root web area should be
-   *               returned; otherwise the desktop will be returned.
    */
   runWithLoadedTree(doc, callback, opt_params = {}) {
     callback = this.newCallback(callback);
@@ -111,9 +122,10 @@
 
         desktop.removeEventListener('focus', listener, true);
         desktop.removeEventListener('loadComplete', listener, true);
-        callback && callback(opt_params.returnPage ? event.target : desktop);
+        callback && callback(event.target);
         callback = null;
       };
+
       this.desktop_ = desktop;
       desktop.addEventListener('focus', listener, true);
       desktop.addEventListener('loadComplete', listener, true);
diff --git a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_accessibility_private.js b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_accessibility_private.js
index 1e17264..df7bc4a 100644
--- a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_accessibility_private.js
+++ b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_accessibility_private.js
@@ -19,6 +19,7 @@
   /** @private {!Array<!chrome.accessibilityPrivate.ScreenRect>} */
   focusRingRects_: [],
   handleScrollableBoundsForPointFoundCallback_: null,
+  moveMagnifierToRectCallback_: null,
 
   // Methods from AccessibilityPrivate API. //
 
@@ -28,15 +29,15 @@
      * @param {function<number, number>} listener
      */
     addListener: (listener) => {
-      boundsListener_ = listener;
+      MockAccessibilityPrivate.boundsListener_ = listener;
     },
 
     /**
      * Removes the listener.
      */
     removeListener: (listener) => {
-      if (boundsListener_ == listener) {
-        boundsListener_ = null;
+      if (MockAccessibilityPrivate.boundsListener_ == listener) {
+        MockAccessibilityPrivate.boundsListener_ = null;
       }
     }
   },
@@ -46,8 +47,17 @@
    * @param {!chrome.accessibilityPrivate.ScreenRect} bounds
    */
   handleScrollableBoundsForPointFound: (bounds) => {
-    scrollableBounds_ = bounds;
-    handleScrollableBoundsForPointFoundCallback_();
+    MockAccessibilityPrivate.scrollableBounds_ = bounds;
+    MockAccessibilityPrivate.handleScrollableBoundsForPointFoundCallback_();
+  },
+
+  /**
+   * Called when AccessibilityCommon wants to move the magnifier viewport to
+   * include a specific rect.
+   * @param {!chrome.accessibilityPrivate.ScreenRect} rect
+   */
+  moveMagnifierToRect: (rect) => {
+    MockAccessibilityPrivate.moveMagnifierToRectCallback_(rect);
   },
 
   /**
@@ -57,7 +67,7 @@
    * @param {!Array<!FocusRingInfo>} focusRingInfos
    */
   setFocusRings: (focusRingInfos) => {
-    focusRingRects_ = focusRingInfos[0].rects;
+    MockAccessibilityPrivate.focusRingRects_ = focusRingInfos[0].rects;
   },
 
   // Methods for testing. //
@@ -75,18 +85,29 @@
    */
   callOnScrollableBoundsForPointRequested:
       (x, y, handleScrollableBoundsForPointFoundCallback) => {
-        handleScrollableBoundsForPointFoundCallback_ =
+        MockAccessibilityPrivate.handleScrollableBoundsForPointFoundCallback_ =
             handleScrollableBoundsForPointFoundCallback;
-        boundsListener_(x, y);
+        MockAccessibilityPrivate.boundsListener_(x, y);
       },
 
   /**
+   * Called to register a stubbed callback for moveMagnifierToRect.
+   * When magnifier identifies a desired rect to move the viewport to,
+   * moveMagnifierToRectCallback will be called with that desired rect.
+   * @param {!function<>} moveMagnifierToRectCallback
+   */
+  registerMoveMagnifierToRectCallback: (moveMagnifierToRectCallback) => {
+    MockAccessibilityPrivate.moveMagnifierToRectCallback_ =
+        moveMagnifierToRectCallback;
+  },
+
+  /**
    * Gets the scrollable bounds which were found by the AccessibilityCommon
    * extension.
    * @return {Array<!chrome.AccessibilityPrivate.ScreenRect>}
    */
   getScrollableBounds: () => {
-    return scrollableBounds_;
+    return MockAccessibilityPrivate.scrollableBounds_;
   },
 
   /**
@@ -95,6 +116,6 @@
    * @return {Array<!chrome.AccessibilityPrivate.ScreenRect>}
    */
   getFocusRings: () => {
-    return focusRingRects_;
+    return MockAccessibilityPrivate.focusRingRects_;
   },
 };
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_keystroke_selection_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_keystroke_selection_test.js
index 5e07a7da..a81c519 100644
--- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_keystroke_selection_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_keystroke_selection_test.js
@@ -47,11 +47,11 @@
    *     extra whitespace, after this selection is triggered.
    */
   testSimpleTextAtKeystroke(text, anchorOffset, focusOffset, expected) {
-    this.testReadTextAtKeystroke('<p>' + text + '</p>', function(desktop) {
+    this.testReadTextAtKeystroke('<p>' + text + '</p>', function(root) {
       // Set the document selection. This will fire the changed event
       // above, allowing us to do the keystroke and test that speech
       // occurred properly.
-      const textNode = this.findTextNode(desktop, 'This is some text');
+      const textNode = this.findTextNode(root, 'This is some text');
       chrome.automation.setDocumentSelection({
         anchorObject: textNode,
         anchorOffset,
@@ -78,21 +78,20 @@
    */
   testReadTextAtKeystroke(contents, setFocusCallback, expected) {
     setFocusCallback = this.newCallback(setFocusCallback);
-    this.runWithLoadedTree(
-        contents, function(desktop) {
-          // Add an event listener that will start the user interaction
-          // of the test once the selection is completed.
-          desktop.addEventListener(
-              'documentSelectionChanged', this.newCallback(function(event) {
-                this.triggerReadSelectedText();
-                assertTrue(this.mockTts.currentlySpeaking());
-                assertEquals(this.mockTts.pendingUtterances().length, 1);
-                this.assertEqualsCollapseWhitespace(
-                    this.mockTts.pendingUtterances()[0], expected);
-              }),
-              false);
-          setFocusCallback(desktop);
-        });
+    this.runWithLoadedTree(contents, function(root) {
+      // Add an event listener that will start the user interaction
+      // of the test once the selection is completed.
+      root.addEventListener(
+          'documentSelectionChanged', this.newCallback(function(event) {
+            this.triggerReadSelectedText();
+            assertTrue(this.mockTts.currentlySpeaking());
+            assertEquals(this.mockTts.pendingUtterances().length, 1);
+            this.assertEqualsCollapseWhitespace(
+                this.mockTts.pendingUtterances()[0], expected);
+          }),
+          false);
+      setFocusCallback(root);
+    });
   }
 
   generateHtmlWithSelection(selectionCode, bodyHtml) {
@@ -138,9 +137,9 @@
     function() {
       this.testReadTextAtKeystroke(
           '<p>This is some <b>bold</b> text</p><p>Second paragraph</p>',
-          function(desktop) {
-            const firstNode = this.findTextNode(desktop, 'This is some ');
-            const lastNode = this.findTextNode(desktop, ' text');
+          function(root) {
+            const firstNode = this.findTextNode(root, 'This is some ');
+            const lastNode = this.findTextNode(root, ' text');
             chrome.automation.setDocumentSelection({
               anchorObject: firstNode,
               anchorOffset: 0,
@@ -156,10 +155,10 @@
     'SpeaksAcrossNodesSelectedBackwardsAtKeystroke', function() {
       this.testReadTextAtKeystroke(
           '<p>This is some <b>bold</b> text</p><p>Second paragraph</p>',
-          function(desktop) {
+          function(root) {
             // Set the document selection backwards in page order.
-            const lastNode = this.findTextNode(desktop, 'This is some ');
-            const firstNode = this.findTextNode(desktop, ' text');
+            const lastNode = this.findTextNode(root, 'This is some ');
+            const firstNode = this.findTextNode(root, ' text');
             chrome.automation.setDocumentSelection({
               anchorObject: firstNode,
               anchorOffset: 5,
@@ -176,9 +175,9 @@
       // If you load this html and double-click on "Selected text", this is the
       // document selection that occurs -- into the second <br/> element.
 
-      let setFocusCallback = function(desktop) {
-        const firstNode = this.findTextNode(desktop, 'Selected text');
-        const lastNode = desktop.findAll({role: 'lineBreak'})[1];
+      let setFocusCallback = function(root) {
+        const firstNode = this.findTextNode(root, 'Selected text');
+        const lastNode = root.findAll({role: 'lineBreak'})[1];
         chrome.automation.setDocumentSelection({
           anchorObject: firstNode,
           anchorOffset: 0,
@@ -188,10 +187,10 @@
       };
       setFocusCallback = this.newCallback(setFocusCallback);
       this.runWithLoadedTree(
-          '<br/><p>Selected text</p><br/>', function(desktop) {
+          '<br/><p>Selected text</p><br/>', function(root) {
             // Add an event listener that will start the user interaction
             // of the test once the selection is completed.
-            desktop.addEventListener(
+            root.addEventListener(
                 'documentSelectionChanged', this.newCallback(function(event) {
                   this.triggerReadSelectedText();
                   assertTrue(this.mockTts.currentlySpeaking());
@@ -203,7 +202,7 @@
                   }
                 }),
                 false);
-            setFocusCallback(desktop);
+            setFocusCallback(root);
           });
     });
 
@@ -212,10 +211,10 @@
     function() {
       this.testReadTextAtKeystroke(
           '<div id="empty"></div><div><p>This is some <b>bold</b> text</p></div>',
-          function(desktop) {
+          function(root) {
             const firstNode =
-                this.findTextNode(desktop, 'This is some ').root.children[0];
-            const lastNode = this.findTextNode(desktop, ' text');
+                this.findTextNode(root, 'This is some ').root.children[0];
+            const lastNode = this.findTextNode(root, ' text');
             chrome.automation.setDocumentSelection({
               anchorObject: firstNode,
               anchorOffset: 0,
@@ -231,10 +230,10 @@
     function() {
       this.testReadTextAtKeystroke(
           '<div><p>This is some <span style="user-select:none">unselectable</span> text</p></div>',
-          function(desktop) {
+          function(root) {
             const firstNode =
-                this.findTextNode(desktop, 'This is some ').root.children[0];
-            const lastNode = this.findTextNode(desktop, ' text');
+                this.findTextNode(root, 'This is some ').root.children[0];
+            const lastNode = this.findTextNode(root, ' text');
             chrome.automation.setDocumentSelection({
               anchorObject: firstNode,
               anchorOffset: 0,
@@ -249,8 +248,8 @@
     'SelectToSpeakKeystrokeSelectionTest',
     'HandlesSingleImageCorrectlyWithAutomation', function() {
       this.testReadTextAtKeystroke(
-          '<img src="pipe.jpg" alt="one"/>', function(desktop) {
-            const container = desktop.findAll({role: 'genericContainer'})[0];
+          '<img src="pipe.jpg" alt="one"/>', function(root) {
+            const container = root.findAll({role: 'genericContainer'})[0];
             chrome.automation.setDocumentSelection({
               anchorObject: container,
               anchorOffset: 0,
@@ -266,8 +265,8 @@
       this.testReadTextAtKeystroke(
           '<img src="pipe.jpg" alt="one"/>' +
               '<img src="pipe.jpg" alt="two"/><img src="pipe.jpg" alt="three"/>',
-          function(desktop) {
-            const container = desktop.findAll({role: 'genericContainer'})[0];
+          function(root) {
+            const container = root.findAll({role: 'genericContainer'})[0];
             chrome.automation.setDocumentSelection({
               anchorObject: container,
               anchorOffset: 1,
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js
index 3ce1d890..7ef7836 100644
--- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js
@@ -48,7 +48,7 @@
   this.runWithLoadedTree(
       'data:text/html;charset=utf-8,' +
           '<p>This is some text</p>',
-      function(desktop) {
+      function(root) {
         assertFalse(this.mockTts.currentlySpeaking());
         assertEquals(this.mockTts.pendingUtterances().length, 0);
         this.mockTts.setOnSpeechCallbacks(
@@ -59,7 +59,7 @@
               this.assertEqualsCollapseWhitespace(
                   this.mockTts.pendingUtterances()[0], 'This is some text');
             })]);
-        const textNode = this.findTextNode(desktop, 'This is some text');
+        const textNode = this.findTextNode(root, 'This is some text');
         const event = {
           screenX: textNode.location.left + 1,
           screenY: textNode.location.top + 1
@@ -74,7 +74,7 @@
       this.runWithLoadedTree(
           'data:text/html;charset=utf-8,' +
               '<p>This is some text</p><p>This is some more text</p>',
-          function(desktop) {
+          function(root) {
             assertFalse(this.mockTts.currentlySpeaking());
             assertEquals(this.mockTts.pendingUtterances().length, 0);
             this.mockTts.setOnSpeechCallbacks([
@@ -89,13 +89,12 @@
                     utterance, 'This is some more text');
               })
             ]);
-            const firstNode = this.findTextNode(desktop, 'This is some text');
+            const firstNode = this.findTextNode(root, 'This is some text');
             const downEvent = {
               screenX: firstNode.location.left + 1,
               screenY: firstNode.location.top + 1
             };
-            const lastNode =
-                this.findTextNode(desktop, 'This is some more text');
+            const lastNode = this.findTextNode(root, 'This is some more text');
             const upEvent = {
               screenX: lastNode.location.left + lastNode.location.width,
               screenY: lastNode.location.top + lastNode.location.height
@@ -111,7 +110,7 @@
           'data:text/html;charset=utf-8,' +
               '<p style="width:200px">This is some text in a paragraph that wraps. ' +
               '<i>Italic text</i></p>',
-          function(desktop) {
+          function(root) {
             assertFalse(this.mockTts.currentlySpeaking());
             assertEquals(this.mockTts.pendingUtterances().length, 0);
             this.mockTts.setOnSpeechCallbacks(
@@ -124,12 +123,12 @@
                           'Italic text');
                 })]);
             const firstNode = this.findTextNode(
-                desktop, 'This is some text in a paragraph that wraps. ');
+                root, 'This is some text in a paragraph that wraps. ');
             const downEvent = {
               screenX: firstNode.location.left + 1,
               screenY: firstNode.location.top + 1
             };
-            const lastNode = this.findTextNode(desktop, 'Italic text');
+            const lastNode = this.findTextNode(root, 'Italic text');
             const upEvent = {
               screenX: lastNode.location.left + lastNode.location.width,
               screenY: lastNode.location.top + lastNode.location.height
@@ -144,7 +143,7 @@
       this.runWithLoadedTree(
           'data:text/html;charset=utf-8,' +
               '<p>This is some text</p>',
-          function(desktop) {
+          function(root) {
             assertFalse(this.mockTts.currentlySpeaking());
             this.mockTts.setOnSpeechCallbacks(
                 [this.newCallback(function(utterance) {
@@ -155,13 +154,14 @@
                       this.mockTts.pendingUtterances()[0], 'This is some text');
                 })]);
 
-            const textNode = this.findTextNode(desktop, 'This is some text');
+            const textNode = this.findTextNode(root, 'This is some text');
             const event = {
               screenX: textNode.location.left + 1,
               screenY: textNode.location.top + 1
             };
             // A state change request should shift us into 'selecting' state
             // from 'inactive'.
+            const desktop = root.parent.root;
             this.tapTrayButton(desktop, () => {
               selectToSpeak.fireMockMouseDownEvent(event);
               selectToSpeak.fireMockMouseUpEvent(event);
@@ -175,14 +175,15 @@
       this.runWithLoadedTree(
           'data:text/html;charset=utf-8,' +
               '<p>This is some text</p>',
-          function(desktop) {
-            const textNode = this.findTextNode(desktop, 'This is some text');
+          function(root) {
+            const textNode = this.findTextNode(root, 'This is some text');
             const event = {
               screenX: textNode.location.left + 1,
               screenY: textNode.location.top + 1
             };
             // A state change request should shift us into 'selecting' state
             // from 'inactive'.
+            const desktop = root.parent.root;
             this.tapTrayButton(desktop, () => {
               selectToSpeak.fireMockMouseDownEvent(event);
               assertEquals(SelectToSpeakState.SELECTING, selectToSpeak.state_);
@@ -200,7 +201,7 @@
       this.runWithLoadedTree(
           'data:text/html;charset=utf-8,' +
               '<p>This is some text</p>',
-          function(desktop) {
+          function(root) {
             assertFalse(this.mockTts.currentlySpeaking());
             assertEquals(this.mockTts.pendingUtterances().length, 0);
             this.mockTts.setOnSpeechCallbacks(
@@ -212,6 +213,7 @@
                       this.mockTts.pendingUtterances()[0], 'This is some text');
 
                   // Cancel speech and make sure state resets to INACTIVE.
+                  const desktop = root.parent.root;
                   this.tapTrayButton(desktop, () => {
                     assertFalse(this.mockTts.currentlySpeaking());
                     assertEquals(this.mockTts.pendingUtterances().length, 0);
@@ -219,7 +221,7 @@
                         SelectToSpeakState.INACTIVE, selectToSpeak.state_);
                   });
                 })]);
-            const textNode = this.findTextNode(desktop, 'This is some text');
+            const textNode = this.findTextNode(root, 'This is some text');
             const event = {
               screenX: textNode.location.left + 1,
               screenY: textNode.location.top + 1
@@ -237,7 +239,7 @@
       // stylus may act as a laser pointer unless it taps on the stylus options
       // button, which always opens on a tap regardless of the stylus behavior
       // selected.
-      chrome.automation.getDesktop(this.newCallback((desktop) => {
+      this.runWithLoadedDesktop((desktop) => {
         this.tapTrayButton(desktop, () => {
           assertEquals(selectToSpeak.state_, SelectToSpeakState.SELECTING);
           const button = desktop.find({
@@ -266,5 +268,5 @@
           selectToSpeak.fireMockMouseDownEvent(event);
           selectToSpeak.fireMockMouseUpEvent(event);
         });
-      }));
+      });
     });
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/auto_scan_manager_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/auto_scan_manager_test.js
index 388cb42..d56e5b62 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/auto_scan_manager_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/auto_scan_manager_test.js
@@ -47,7 +47,7 @@
 };
 
 TEST_F('SwitchAccessAutoScanManagerTest', 'SetEnabled', function() {
-  this.runWithLoadedTree('', (desktop) => {
+  this.runWithLoadedTree('', () => {
     assertFalse(
         AutoScanManager.instance.isRunning_(),
         'Auto scan manager is running prematurely');
@@ -76,7 +76,7 @@
 });
 
 TEST_F('SwitchAccessAutoScanManagerTest', 'SetEnabledMultiple', function() {
-  this.runWithLoadedTree('', (desktop) => {
+  this.runWithLoadedDesktop(() => {
     assertFalse(
         AutoScanManager.instance.isRunning_(),
         'Auto scan manager is running prematurely');
@@ -94,7 +94,7 @@
 });
 
 TEST_F('SwitchAccessAutoScanManagerTest', 'EnableAndDisable', function() {
-  this.runWithLoadedTree('', (desktop) => {
+  this.runWithLoadedDesktop(() => {
     assertFalse(
         AutoScanManager.instance.isRunning_(),
         'Auto scan manager is running prematurely');
@@ -116,7 +116,7 @@
 
 TEST_F(
     'SwitchAccessAutoScanManagerTest', 'RestartIfRunningMultiple', function() {
-      this.runWithLoadedTree('', (desktop) => {
+      this.runWithLoadedDesktop(() => {
         assertFalse(
             AutoScanManager.instance.isRunning_(),
             'Auto scan manager is running prematurely');
@@ -140,7 +140,7 @@
 
 TEST_F(
     'SwitchAccessAutoScanManagerTest', 'RestartIfRunningWhenOff', function() {
-      this.runWithLoadedTree('', (desktop) => {
+      this.runWithLoadedDesktop(() => {
         assertFalse(
             AutoScanManager.instance.isRunning_(),
             'Auto scan manager is running at start.');
@@ -152,7 +152,7 @@
     });
 
 TEST_F('SwitchAccessAutoScanManagerTest', 'SetPrimaryScanTime', function() {
-  this.runWithLoadedTree('', (desktop) => {
+  this.runWithLoadedDesktop(() => {
     assertFalse(
         AutoScanManager.instance.isRunning_(),
         'Auto scan manager is running prematurely');
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager_test.js
index cd1c62d..2f52851f 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager_test.js
@@ -42,7 +42,8 @@
                      </div>
                      <button></button>
                    </div>`;
-  this.runWithLoadedTree(website, (desktop) => {
+  this.runWithLoadedTree(website, (root) => {
+    const desktop = root.parent.root;
     const textFields =
         desktop.findAll({role: chrome.automation.RoleType.TEXT_FIELD});
     assertEquals(2, textFields.length, 'Should be exactly 2 text fields.');
@@ -105,7 +106,8 @@
                      <button></button>
                      <button></button>
                    </div>`;
-  this.runWithLoadedTree(website, (desktop) => {
+  this.runWithLoadedTree(website, (root) => {
+    const desktop = root.parent.root;
     const textInput =
         desktop.findAll({role: chrome.automation.RoleType.TEXT_FIELD})[1];
     assertNotNullNorUndefined(textInput, 'Text field is undefined');
@@ -163,7 +165,7 @@
         }));
 
     NavigationManager.instance.node_.performAction('select');
-  }, {returnPage: true});
+  });
 });
 
 TEST_F('SwitchAccessNavigationManagerTest', 'EnterGroup', function() {
@@ -172,7 +174,7 @@
                      <button></button>
                    </div>
                    <input type="range">`;
-  this.runWithLoadedTree(website, (desktop) => {
+  this.runWithLoadedTree(website, (root) => {
     const targetGroup = this.findNodeById('group');
     this.navigator.moveTo_(targetGroup);
 
@@ -202,7 +204,7 @@
                      <button id="button2"></button>
                      <button id="button3"></button>
                    </div>`;
-  this.runWithLoadedTree(website, (desktop) => {
+  this.runWithLoadedTree(website, (root) => {
     this.navigator.moveTo_(this.findNodeById('button1'));
     const button1 = this.navigator.node_;
     assertFalse(
@@ -257,7 +259,7 @@
                      <button id="button2"></button>
                      <button id="button3"></button>
                    </div>`;
-  this.runWithLoadedTree(website, (desktop) => {
+  this.runWithLoadedTree(website, (root) => {
     this.navigator.moveTo_(this.findNodeById('button1'));
     const button1 = this.navigator.node_;
     assertFalse(
@@ -310,7 +312,7 @@
       const website = `<div>
                      <button id="button1"></button>
                    </div>`;
-      this.runWithLoadedTree(website, (desktop) => {
+      this.runWithLoadedTree(website, (root) => {
         this.navigator.moveTo_(this.findNodeById('button1'));
         const button1 = this.navigator.node_;
         assertFalse(
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node_test.js
index 20bf8d90..7685a31 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node_test.js
@@ -15,8 +15,8 @@
                      </div>
                      <button></button>
                    </div>`;
-  this.runWithLoadedTree(website, (desktop) => {
-    const slider = desktop.find({role: chrome.automation.RoleType.SLIDER});
+  this.runWithLoadedTree(website, (root) => {
+    const slider = root.find({role: chrome.automation.RoleType.SLIDER});
     const inner = slider.parent;
     assertNotEquals(undefined, inner, 'Could not find inner group');
     const outer = inner.parent;
@@ -42,7 +42,7 @@
 });
 
 TEST_F('SwitchAccessBasicNodeTest', 'Equals', function() {
-  this.runWithLoadedTree('', (desktop) => {
+  this.runWithLoadedDesktop((desktop) => {
     const desktopNode = DesktopNode.build(desktop);
 
     let childGroup = desktopNode.firstChild;
@@ -115,9 +115,9 @@
   const website = `<input type="text">
                    <button></button>
                    <input type="range" min=1 max=5 value=3>`;
-  this.runWithLoadedTree(website, (desktop) => {
+  this.runWithLoadedTree(website, (root) => {
     const textField = BasicNode.create(
-        desktop.find({role: chrome.automation.RoleType.TEXT_FIELD}),
+        root.find({role: chrome.automation.RoleType.TEXT_FIELD}),
         new SARootNode());
 
     assertEquals(
@@ -134,8 +134,7 @@
         'Text field has action SELECT');
 
     const button = BasicNode.create(
-        desktop.find({role: chrome.automation.RoleType.BUTTON}),
-        new SARootNode());
+        root.find({role: chrome.automation.RoleType.BUTTON}), new SARootNode());
 
     assertEquals(
         chrome.automation.RoleType.BUTTON, button.role,
@@ -151,8 +150,7 @@
         'Button has action DICTATION');
 
     const slider = BasicNode.create(
-        desktop.find({role: chrome.automation.RoleType.SLIDER}),
-        new SARootNode());
+        root.find({role: chrome.automation.RoleType.SLIDER}), new SARootNode());
 
     assertEquals(
         chrome.automation.RoleType.SLIDER, slider.role,
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node_test.js
index cb3b50e..a48f1d26 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node_test.js
@@ -8,7 +8,7 @@
 SwitchAccessDesktopNodeTest = class extends SwitchAccessE2ETest {};
 
 TEST_F('SwitchAccessDesktopNodeTest', 'Build', function() {
-  this.runWithLoadedTree('', (desktop) => {
+  this.runWithLoadedDesktop((desktop) => {
     const desktopNode = DesktopNode.build(desktop);
 
     const children = desktopNode.children;
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js
index 76fa76f..e78c0aa 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js
@@ -9,11 +9,11 @@
 
 TEST_F('SwitchAccessGroupNodeTest', 'NodesRemoved', function() {
   const website = `<button></button>`;
-  this.runWithLoadedTree(website, (desktop) => {
-    const button = desktop.find({role: chrome.automation.RoleType.BUTTON});
+  this.runWithLoadedTree(website, (rootNode) => {
+    const button = rootNode.find({role: chrome.automation.RoleType.BUTTON});
     assertNotEquals(undefined, button);
 
-    const root = new BasicRootNode(desktop);
+    const root = new BasicRootNode(rootNode);
     assertEquals(0, root.children_.length);
 
     // Add a group child which has two buttons (same underlying automation
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/tab_node_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/tab_node_test.js
index 61cfd6a..ec622c44 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/tab_node_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/tab_node_test.js
@@ -8,7 +8,7 @@
 SwitchAccessTabNodeTest = class extends SwitchAccessE2ETest {};
 
 TEST_F('SwitchAccessTabNodeTest', 'FindCloseButton', function() {
-  this.runWithLoadedTree('', (desktop) => {
+  this.runWithLoadedDesktop((desktop) => {
     const tab = desktop.find({role: chrome.automation.RoleType.TAB});
 
     // To find the close button, Switch Access relies on it being the only
@@ -24,7 +24,7 @@
 });
 
 TEST_F('SwitchAccessTabNodeTest', 'Construction', function() {
-  this.runWithLoadedTree('', (desktop) => {
+  this.runWithLoadedDesktop((desktop) => {
     NavigationManager.instance.moveTo_(
         desktop.find({role: chrome.automation.RoleType.TAB}));
 
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate_test.js
index 7015510..a39b5cd 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate_test.js
@@ -128,7 +128,7 @@
     assertFalse(
         SwitchAccessPredicate.isInteresting(t.leaf7, null, cache),
         'Leaf7 should not be interesting');
-  }, {returnPage: true});
+  });
 });
 
 TEST_F('SwitchAccessPredicateTest', 'IsGroup', function() {
@@ -178,7 +178,7 @@
     assertFalse(
         SwitchAccessPredicate.isGroup(t.leaf7, null, cache),
         'Leaf7 should not be a group');
-  }, {returnPage: true});
+  });
 });
 
 TEST_F('SwitchAccessPredicateTest', 'IsInterestingSubtree', function() {
@@ -225,7 +225,7 @@
     assertFalse(
         SwitchAccessPredicate.isInterestingSubtree(t.leaf7, cache),
         'Leaf7 should not be an interesting subtree');
-  }, {returnPage: true});
+  });
 });
 
 TEST_F('SwitchAccessPredicateTest', 'IsActionable', function() {
@@ -238,7 +238,7 @@
        <input type="range" aria-label="slider" value=5 min=0 max=10>
        <div id="clickable" role="listitem" onclick="2+2"></div>
        <div aria-label="div1"><p>p1</p></div>`;
-  this.runWithLoadedTree(treeString, (desktop) => {
+  this.runWithLoadedTree(treeString, (loadedPage) => {
     const cache = new SACache();
 
     const offscreenButton = this.findNodeByNameAndRole('offscreen', 'button');
@@ -251,13 +251,9 @@
         SwitchAccessPredicate.isActionable(disabledButton, cache),
         'Disabled objects should not be actionable');
 
-    const rwas =
-        desktop.findAll({role: chrome.automation.RoleType.ROOT_WEB_AREA});
-    for (const node of rwas) {
-      assertFalse(
-          SwitchAccessPredicate.isActionable(node, cache),
-          'Root web area should not be directly actionable');
-    }
+    assertFalse(
+        SwitchAccessPredicate.isActionable(loadedPage, cache),
+        'Root web area should not be directly actionable');
 
     const link1 = this.findNodeByNameAndRole('link1', 'link');
     assertTrue(
@@ -318,7 +314,7 @@
          <p>p2</p>
          <p>p3</p>
        </div>`;
-  this.runWithLoadedTree(treeString, (desktop) => {
+  this.runWithLoadedTree(treeString, (loadedPage) => {
     const cache = new SACache();
 
     const noChildren = this.findNodeById('noChildren');
@@ -372,7 +368,7 @@
     assertTrue(leaf(t.leaf1), 'Leaf1 should be a leaf for lower1 tree');
     assertTrue(leaf(t.leaf2), 'Leaf2 should be a leaf for lower1 tree');
     assertTrue(leaf(t.leaf3), 'Leaf3 should be a leaf for lower1 tree');
-  }, {returnPage: true});
+  });
 });
 
 TEST_F('SwitchAccessPredicateTest', 'RootPredicate', function() {
@@ -399,7 +395,7 @@
     assertFalse(root(t.leaf1), 'Leaf1 should not be a root of the lower1 tree');
     assertFalse(root(t.leaf2), 'Leaf2 should not be a root of the lower1 tree');
     assertFalse(root(t.leaf3), 'Leaf3 should not be a root of the lower1 tree');
-  }, {returnPage: true});
+  });
 });
 
 TEST_F('SwitchAccessPredicateTest', 'VisitPredicate', function() {
@@ -432,7 +428,7 @@
     assertFalse(visit(t.lower3), 'Lower3 should not be visited in lower1 tree');
     assertFalse(visit(t.leaf6), 'Leaf6 should not be visited in lower1 tree');
     assertFalse(visit(t.leaf7), 'Leaf7 should not be visited in lower1 tree');
-  }, {returnPage: true});
+  });
 });
 
 TEST_F('SwitchAccessPredicateTest', 'Cache', function() {
@@ -476,5 +472,5 @@
     assertEquals(
         locationAccessCount, 1,
         'Cache should have been used, avoiding second location access');
-  }, {returnPage: true});
+  });
 });
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager_test.js
index 20505703..d225dcf 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager_test.js
@@ -45,7 +45,7 @@
   const website = generateWebsiteWithTextArea(
       textId, textContent, initialTextIndex, textCols, textWrap);
 
-  testHelper.runWithLoadedTree(website, function(desktop) {
+  testHelper.runWithLoadedTree(website, function(root) {
     const inputNode = this.findNodeById(textId);
     assertNotEquals(inputNode, null);
 
@@ -104,7 +104,7 @@
     navigationTargetIndex = targetTextStartIndex;
   }
 
-  testHelper.runWithLoadedTree(website, function(desktop) {
+  testHelper.runWithLoadedTree(website, function(root) {
     const inputNode = this.findNodeById(textId);
     assertNotEquals(inputNode, null);
     checkNodeIsFocused(inputNode);
@@ -314,7 +314,7 @@
       const website =
           generateWebsiteWithTextArea('test', 'test123', 3, 20, 'hard');
 
-      this.runWithLoadedTree(website, function(desktop) {
+      this.runWithLoadedTree(website, function(root) {
         const inputNode = this.findNodeById('test');
         assertNotEquals(inputNode, null);
         checkNodeIsFocused(inputNode);
@@ -335,7 +335,7 @@
       const website =
           generateWebsiteWithTextArea('test', 'test 123', 6, 20, 'hard');
 
-      this.runWithLoadedTree(website, function(desktop) {
+      this.runWithLoadedTree(website, function(root) {
         const inputNode = this.findNodeById('test');
         assertNotEquals(inputNode, null);
         checkNodeIsFocused(inputNode);
diff --git a/chrome/browser/resources/extensions/BUILD.gn b/chrome/browser/resources/extensions/BUILD.gn
index c438bc6..385008e 100644
--- a/chrome/browser/resources/extensions/BUILD.gn
+++ b/chrome/browser/resources/extensions/BUILD.gn
@@ -14,11 +14,14 @@
 preprocess_gen_manifest = "preprocessed_gen_manifest.json"
 
 if (optimize_webui) {
+  build_manifest = "build_manifest.json"
+
   optimize_webui("build") {
     host = "extensions"
     input = rebase_path("$target_gen_dir/$preprocess_folder", root_build_dir)
     js_out_files = [ "extensions.rollup.js" ]
     js_module_in_files = [ "extensions.js" ]
+    out_manifest = "$target_gen_dir/$build_manifest"
 
     deps = [
       ":preprocess",
@@ -27,8 +30,22 @@
     ]
     excludes = [ "chrome://resources/js/cr.m.js" ]
   }
-} else {
-  generate_grd("build_grd") {
+}
+
+generate_grd("build_grd") {
+  grd_prefix = "extensions"
+  out_grd = "$target_gen_dir/${grd_prefix}_resources.grd"
+  input_files = [
+    "checkup_image_dark.svg",
+    "checkup_image.svg",
+    "extensions.html",
+  ]
+  input_files_base_dir = rebase_path(".", "//")
+
+  if (optimize_webui) {
+    deps = [ ":build" ]
+    manifest_files = [ "$target_gen_dir/$build_manifest" ]
+  } else {
     deps = [
       ":preprocess",
       ":preprocess_generated",
@@ -37,8 +54,6 @@
       "$target_gen_dir/$preprocess_manifest",
       "$target_gen_dir/$preprocess_gen_manifest",
     ]
-    grd_prefix = "extensions"
-    out_grd = "$target_gen_dir/${grd_prefix}_resources.grd"
   }
 }
 
@@ -55,12 +70,6 @@
     "navigation_helper.js",
     "service.js",
     "shortcut_util.js",
-
-    # TODO(dpapad): Pass these directly to the generate_grd() target above, once
-    # support for that is added, as part of crbug.com/1132403.
-    "extensions.html",
-    "checkup_image_dark.svg",
-    "checkup_image.svg",
   ]
 
   if (is_chromeos) {
diff --git a/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd b/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd
deleted file mode 100644
index c8cbd99..0000000
--- a/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
-  <outputs>
-    <output filename="grit/extensions_resources.h" type="rc_header">
-      <emit emit_type='prepend'></emit>
-    </output>
-    <output filename="grit/extensions_resources_map.cc"
-            type="resource_map_source" />
-    <output filename="grit/extensions_resources_map.h"
-            type="resource_map_header" />
-    <output filename="extensions_resources.pak" type="data_package" />
-  </outputs>
-  <release seq="1">
-    <includes>
-      <include name="IDR_EXTENSIONS_EXTENSIONS_HTML"
-               file="extensions.html"
-               type="chrome_html" />
-      <include name="IDR_EXTENSIONS_EXTENSIONS_ROLLUP_JS"
-               file="${root_gen_dir}\chrome\browser\resources\extensions\extensions.rollup.js"
-               use_base_dir="false"
-               type="BINDATA" />
-      <include name="IDR_EXTENSIONS_CHECKUP_IMAGE"
-               file="checkup_image.svg"
-               type="BINDATA" />
-      <include name="IDR_EXTENSIONS_CHECKUP_IMAGE_DARK"
-               file="checkup_image_dark.svg"
-               type="BINDATA" />
-    </includes>
-  </release>
-</grit>
diff --git a/chrome/browser/resources/new_tab_page/voice_search_overlay.html b/chrome/browser/resources/new_tab_page/voice_search_overlay.html
index aa95925..6aa190c 100644
--- a/chrome/browser/resources/new_tab_page/voice_search_overlay.html
+++ b/chrome/browser/resources/new_tab_page/voice_search_overlay.html
@@ -68,6 +68,8 @@
   *[text='waiting'],
   *[text='speak'] {
     opacity: 0;
+    /* Hiding overflow to prevent jitter when the content area is narrow. */
+    overflow-x: hidden;
     padding-inline-start: 50px;
   }
 
diff --git a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
index 116e1919..acf368f 100644
--- a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
@@ -32,6 +32,7 @@
 #include "chrome/browser/subresource_filter/test_ruleset_publisher.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -818,6 +819,154 @@
   EXPECT_EQ(base::ASCIIToUTF16("failed"), title_watcher.WaitAndGetTitle());
 }
 
+IN_PROC_BROWSER_TEST_F(SubresourceFilterBrowserTest,
+                       PopupsInheritActivation_ResourcesBlocked) {
+  ASSERT_NO_FATAL_FAILURE(
+      SetRulesetWithRules({testing::CreateSuffixRule("ad=true")}));
+
+  // Block disallowed resources.
+  Configuration config(subresource_filter::mojom::ActivationLevel::kEnabled,
+                       subresource_filter::ActivationScope::ALL_SITES);
+  ResetConfiguration(std::move(config));
+
+  const std::vector<std::string> test_case_scripts = {
+      // Popup to URL
+      "window.open('/subresource_filter/popup.html');",
+
+      // Popup to empty URL
+      "popupLoadsDisallowedResource('');",
+
+      // Child of popup to empty URL
+      "popupLoadsDisallowedResourceAsDescendant('');",
+
+      // Popup to about:blank URL. about:blank popups behave differently to
+      // popups with an empty URL, so we test them separately.
+      "popupLoadsDisallowedResource('about:blank');",
+
+      // Child of popup to about:blank URL
+      "popupLoadsDisallowedResourceAsDescendant('about:blank');",
+
+      // Popup with doc.write-aborted load
+      "popupLoadsDisallowedResource('http://b.com/slow?100');",
+
+      // TODO(alexmt): Enable this test case. Currently disabled as there is no
+      // guarantee that the descendant's navigation starts after the parent's
+      // navigation ends (see crbug.com/1101569).
+      // Child of popup with doc.write-aborted load
+      // "popupLoadsDisallowedResourceAsDescendant('http://b.com/slow?100');",
+
+  };
+
+  for (const auto& test_case_script : test_case_scripts) {
+    content::WebContentsAddedObserver popup_observer;
+    ui_test_utils::NavigateToURL(
+        browser(),
+        embedded_test_server()->GetURL(
+            "/subresource_filter/popup_disallowed_load_helper.html"));
+    ASSERT_TRUE(ExecJs(web_contents(), test_case_script));
+    content::TitleWatcher title_watcher(popup_observer.GetWebContents(),
+                                        base::ASCIIToUTF16("failed"));
+    title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("loaded"));
+
+    // Check the load was blocked.
+    EXPECT_EQ(base::ASCIIToUTF16("failed"), title_watcher.WaitAndGetTitle());
+  }
+}
+
+IN_PROC_BROWSER_TEST_F(SubresourceFilterBrowserTest,
+                       PopupNavigatesBackToAboutBlank_FilterChecked) {
+  ASSERT_NO_FATAL_FAILURE(
+      SetRulesetWithRules({testing::CreateSuffixRule("ad=true")}));
+
+  // Block disallowed resources.
+  Configuration config(subresource_filter::mojom::ActivationLevel::kEnabled,
+                       subresource_filter::ActivationScope::ALL_SITES);
+  ResetConfiguration(std::move(config));
+
+  content::WebContentsAddedObserver popup_observer;
+  ui_test_utils::NavigateToURL(browser(),
+                               embedded_test_server()->GetURL("/title1.html"));
+
+  ASSERT_TRUE(ExecJs(web_contents(),
+                     content::JsReplace("popup = window.open($1, 'name1');",
+                                        embedded_test_server()->GetURL(
+                                            "b.com", "/title2.html"))));
+
+  {
+    content::TitleWatcher title_watcher(
+        popup_observer.GetWebContents(),
+        base::ASCIIToUTF16("Title Of Awesomeness"));
+    // Wait for popup to finish loading
+    EXPECT_EQ(base::ASCIIToUTF16("Title Of Awesomeness"),
+              title_watcher.WaitAndGetTitle());
+  }
+
+  ui_test_utils::NavigateToURL(
+      chrome::FindBrowserWithWebContents(popup_observer.GetWebContents()),
+      GURL("about:blank"));
+
+  ASSERT_TRUE(ExecJs(web_contents(), R"SCRIPT(
+    // Get reference to popup without changing its location.
+    popup = window.open('', 'name1');
+    doc = popup.document;
+    doc.open();
+    doc.write(
+      "<html><body>Rewritten. <img src='/ad_tagging/pixel.png?ad=true' " +
+      "onload='window.document.title = \"loaded\";' " +
+      "onerror='window.document.title = \"failed\";'></body></html>");
+    doc.close();
+    )SCRIPT"));
+
+  content::TitleWatcher title_watcher(popup_observer.GetWebContents(),
+                                      base::ASCIIToUTF16("failed"));
+  title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("loaded"));
+
+  // Check the load was blocked.
+  EXPECT_EQ(base::ASCIIToUTF16("failed"), title_watcher.WaitAndGetTitle());
+}
+
+// Test that resources in a popup with an aborted initial load due to a
+// doc.write are still blocked when disallowed, even if the opener is
+// immediately closed after writing.
+IN_PROC_BROWSER_TEST_F(
+    SubresourceFilterBrowserTest,
+    PopupWithDocWriteAbortedLoadAndOpenerClosed_FilterChecked) {
+  ASSERT_NO_FATAL_FAILURE(
+      SetRulesetWithRules({testing::CreateSuffixRule("ad_script.js"),
+                           testing::CreateSuffixRule("ad=true")}));
+
+  // Block disallowed resources.
+  Configuration config(subresource_filter::mojom::ActivationLevel::kEnabled,
+                       subresource_filter::ActivationScope::ALL_SITES);
+  ResetConfiguration(std::move(config));
+
+  content::WebContents* original_web_contents = web_contents();
+  ui_test_utils::NavigateToURL(browser(),
+                               embedded_test_server()->GetURL("/title1.html"));
+
+  content::WebContentsAddedObserver popup_observer;
+  ASSERT_TRUE(ExecJs(original_web_contents, R"SCRIPT(
+    popup = window.open('http://b.com/slow?100');
+    window.onunload = function(e){
+      doc = popup.document;
+      doc.open();
+      doc.write(
+        "<html><body>Rewritten. <img src='/ad_tagging/pixel.png?ad=true' " +
+        "onload='window.document.title = \"loaded\";' " +
+        "onerror='window.document.title = \"failed\";'></body></html>");
+      doc.close();
+    };
+    )SCRIPT"));
+  original_web_contents->ClosePage();
+
+  content::TitleWatcher title_watcher(popup_observer.GetWebContents(),
+                                      base::ASCIIToUTF16("failed"));
+  title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("loaded"));
+
+  // Check the load was blocked.
+  EXPECT_EQ(base::ASCIIToUTF16("failed"), title_watcher.WaitAndGetTitle());
+}
+
 // Tests checking how histograms are recorded. ---------------------------------
 
 namespace {
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
index 4d640202..ce1725f 100644
--- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
@@ -154,6 +154,9 @@
 void SubresourceFilterContentSettingsManager::SetSiteMetadata(
     const GURL& url,
     std::unique_ptr<base::DictionaryValue> dict) {
+  if (url.is_empty())
+    return;
+
   // Metadata expires after kMaxPersistMetadataDuration by default. If
   // kNonRenewingExpiryTime was previously set, then we are storing ads
   // intervention metadata and should not override the expiry time that
@@ -209,7 +212,7 @@
     history::HistoryService* history_service,
     const history::DeletionInfo& deletion_info) {
   if (deletion_info.IsAllHistory()) {
-    settings_map_->ClearSettingsForOneType(ContentSettingsType::ADS_DATA);
+    ClearMetadataForAllSites();
     return;
   }
 
@@ -217,7 +220,7 @@
     const GURL& origin = entry.first;
     int remaining_urls = entry.second.first;
     if (!origin.is_empty() && remaining_urls == 0)
-      SetSiteMetadata(origin, nullptr);
+      ClearSiteMetadata(origin);
   }
 }
 
@@ -239,3 +242,12 @@
   // kActivatedKey.
   return !site_activation_status || *site_activation_status;
 }
+
+void SubresourceFilterContentSettingsManager::ClearSiteMetadata(
+    const GURL& url) {
+  SetSiteMetadata(url, nullptr);
+}
+
+void SubresourceFilterContentSettingsManager::ClearMetadataForAllSites() {
+  settings_map_->ClearSettingsForOneType(ContentSettingsType::ADS_DATA);
+}
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h
index 6bef2860..469edeba 100644
--- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h
+++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h
@@ -115,6 +115,12 @@
   // class comment for information on the metadata data model.
   bool GetSiteActivationFromMetadata(const GURL& url);
 
+  // Clears metadata for |url|.
+  void ClearSiteMetadata(const GURL& url);
+
+  // Clears metadata for all sites.
+  void ClearMetadataForAllSites();
+
   void set_clock_for_testing(std::unique_ptr<base::Clock> tick_clock) {
     clock_ = std::move(tick_clock);
   }
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc
index 9e1f277..41d7ce1 100644
--- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc
@@ -303,6 +303,62 @@
   EXPECT_FALSE(settings_manager()->GetSiteMetadata(url));
 }
 
+// Tests that ClearSiteMetadata(origin) will result in clearing metadata for all
+// sites whose origin is |origin|, but will not clear metadata for sites with
+// different origins.
+TEST_F(SubresourceFilterContentSettingsManagerTest, ClearSiteMetadata) {
+  GURL initial_url("https://example.test/1");
+  GURL same_origin_url("https://example.test/2");
+  GURL different_origin_url("https://second_example.test/");
+
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(initial_url));
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(same_origin_url));
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(different_origin_url));
+
+  settings_manager()->OnDidShowUI(initial_url);
+  EXPECT_FALSE(settings_manager()->ShouldShowUIForSite(initial_url));
+  EXPECT_FALSE(settings_manager()->ShouldShowUIForSite(same_origin_url));
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(different_origin_url));
+
+  settings_manager()->OnDidShowUI(different_origin_url);
+  EXPECT_FALSE(settings_manager()->ShouldShowUIForSite(initial_url));
+  EXPECT_FALSE(settings_manager()->ShouldShowUIForSite(same_origin_url));
+  EXPECT_FALSE(settings_manager()->ShouldShowUIForSite(different_origin_url));
+
+  settings_manager()->ClearSiteMetadata(initial_url);
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(initial_url));
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(same_origin_url));
+  EXPECT_FALSE(settings_manager()->ShouldShowUIForSite(different_origin_url));
+
+  settings_manager()->ClearSiteMetadata(different_origin_url);
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(initial_url));
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(same_origin_url));
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(different_origin_url));
+}
+
+// Tests that ClearMetadataForAllSites() does indeed clear metadata for all
+// sites.
+TEST_F(SubresourceFilterContentSettingsManagerTest, ClearMetadataForAllSites) {
+  GURL initial_url("https://example.test/1");
+  GURL same_origin_url("https://example.test/2");
+  GURL different_origin_url("https://second_example.test/");
+
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(initial_url));
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(same_origin_url));
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(different_origin_url));
+
+  settings_manager()->OnDidShowUI(initial_url);
+  settings_manager()->OnDidShowUI(different_origin_url);
+  EXPECT_FALSE(settings_manager()->ShouldShowUIForSite(initial_url));
+  EXPECT_FALSE(settings_manager()->ShouldShowUIForSite(same_origin_url));
+  EXPECT_FALSE(settings_manager()->ShouldShowUIForSite(different_origin_url));
+
+  settings_manager()->ClearMetadataForAllSites();
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(initial_url));
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(same_origin_url));
+  EXPECT_TRUE(settings_manager()->ShouldShowUIForSite(different_origin_url));
+}
+
 TEST_F(SubresourceFilterContentSettingsManagerHistoryTest,
        HistoryUrlDeleted_ClearsWebsiteSetting) {
   // Simulate a history already populated with a URL.
diff --git a/chrome/browser/subresource_filter/subresource_filter_popup_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_popup_browsertest.cc
index 03030433..d68bcd44 100644
--- a/chrome/browser/subresource_filter/subresource_filter_popup_browsertest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_popup_browsertest.cc
@@ -317,8 +317,9 @@
       web_contents(), "openWindow()", &opened_window));
   EXPECT_TRUE(opened_window);
 
-  // On the new window, requests should be allowed.
-  EXPECT_FALSE(AreDisallowedRequestsBlocked());
+  // On the new window, requests should be blocked due to the popup inheriting
+  // the activation state.
+  EXPECT_TRUE(AreDisallowedRequestsBlocked());
 
   RoundTripAndVerifyLogMessages(console_observer, web_contents(),
                                 {kActivationConsoleMessage},
diff --git a/chrome/browser/translate/chrome_translate_client.cc b/chrome/browser/translate/chrome_translate_client.cc
index 219e3ed..467b91d 100644
--- a/chrome/browser/translate/chrome_translate_client.cc
+++ b/chrome/browser/translate/chrome_translate_client.cc
@@ -26,6 +26,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/theme_resources.h"
+#include "components/autofill_assistant/browser/public/runtime_manager.h"
 #include "components/language/core/browser/language_model_manager.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/prefs/pref_service.h"
@@ -114,6 +115,11 @@
     per_frame_translate_driver_->set_translate_manager(
         translate_manager_.get());
   }
+
+  auto* assistant_runtime_manager =
+      autofill_assistant::RuntimeManager::GetOrCreateForWebContents(
+          web_contents);
+  assistant_runtime_manager->AddObserver(this);
 }
 
 ChromeTranslateClient::~ChromeTranslateClient() {
@@ -313,6 +319,19 @@
   return TranslateService::IsTranslatableURL(url);
 }
 
+bool ChromeTranslateClient::IsAutofillAssistantRunning() const {
+  auto* assistant_runtime_manager =
+      autofill_assistant::RuntimeManager::GetForWebContents(web_contents());
+  return assistant_runtime_manager && assistant_runtime_manager->GetState() ==
+                                          autofill_assistant::UIState::kShown;
+}
+
+void ChromeTranslateClient::OnStateChanged(autofill_assistant::UIState state) {
+  if (state == autofill_assistant::UIState::kNotShown) {
+    GetTranslateManager()->InitiateTranslation();
+  }
+}
+
 void ChromeTranslateClient::ShowReportLanguageDetectionErrorUI(
     const GURL& report_url) {
 #if defined(OS_ANDROID)
@@ -336,6 +355,12 @@
   // Destroying the TranslateManager now guarantees that it never has to deal
   // with NULL WebContents.
   translate_manager_.reset();
+
+  auto* assistant_runtime_manager =
+      autofill_assistant::RuntimeManager::GetForWebContents(web_contents());
+  if (assistant_runtime_manager) {
+    assistant_runtime_manager->RemoveObserver(this);
+  }
 }
 
 // ContentTranslateDriver::Observer implementation.
diff --git a/chrome/browser/translate/chrome_translate_client.h b/chrome/browser/translate/chrome_translate_client.h
index d93be765..4f40ef55 100644
--- a/chrome/browser/translate/chrome_translate_client.h
+++ b/chrome/browser/translate/chrome_translate_client.h
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "chrome/browser/ui/translate/translate_bubble_model.h"
+#include "components/autofill_assistant/browser/public/runtime_observer.h"
 #include "components/language/core/browser/url_language_histogram.h"
 #include "components/translate/content/browser/content_translate_driver.h"
 #include "components/translate/content/browser/per_frame_content_translate_driver.h"
@@ -43,7 +44,8 @@
     : public translate::TranslateClient,
       public translate::ContentTranslateDriver::Observer,
       public content::WebContentsObserver,
-      public content::WebContentsUserData<ChromeTranslateClient> {
+      public content::WebContentsUserData<ChromeTranslateClient>,
+      public autofill_assistant::RuntimeObserver {
  public:
   ~ChromeTranslateClient() override;
 
@@ -104,11 +106,15 @@
                        bool triggered_from_menu) override;
   bool IsTranslatableURL(const GURL& url) override;
   void ShowReportLanguageDetectionErrorUI(const GURL& report_url) override;
+  bool IsAutofillAssistantRunning() const override;
 
   // ContentTranslateDriver::Observer implementation.
   void OnLanguageDetermined(
       const translate::LanguageDetectionDetails& details) override;
 
+  // autofill_assistant::RuntimeObserver implementation.
+  void OnStateChanged(autofill_assistant::UIState state) override;
+
  private:
   explicit ChromeTranslateClient(content::WebContents* web_contents);
   friend class content::WebContentsUserData<ChromeTranslateClient>;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 16ad388..cc51e2b 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2658,7 +2658,6 @@
       "//chromeos/strings",
       "//chromeos/system",
       "//chromeos/ui/base",
-      "//chromeos/ui/frame",
       "//chromeos/ui/vector_icons",
       "//components/arc",
       "//components/assist_ranker",
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_arc_tracker.cc b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_arc_tracker.cc
index 7c8df621..7fb165b 100644
--- a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_arc_tracker.cc
+++ b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_arc_tracker.cc
@@ -97,6 +97,13 @@
 
 void AppServiceAppWindowArcTracker::OnWindowDestroying(aura::Window* window) {
   app_service_controller_->UnregisterWindow(window);
+  // Replace the pointers to the window by nullptr to prevent from using it
+  // before OnTaskDestroyed() is called to remove the entry from
+  // |task_id_to_arc_app_window_info_|;
+  const int task_id = arc::GetWindowTaskId(window);
+  auto it = task_id_to_arc_app_window_info_.find(task_id);
+  if (it != task_id_to_arc_app_window_info_.end())
+    it->second->set_window(nullptr);
 }
 
 void AppServiceAppWindowArcTracker::OnAppStatesChanged(
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
index 10a65bc..f64ff855 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
@@ -176,7 +176,6 @@
 
   auto dialog_model =
       ui::DialogModel::Builder(std::move(bubble_delegate_unique))
-          .SetShowCloseButton(true)
           .SetTitle(l10n_util::GetStringUTF16(
               already_bookmarked ? IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARK
                                  : IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED))
diff --git a/chrome/browser/ui/views/frame/browser_frame_header_ash.cc b/chrome/browser/ui/views/frame/browser_frame_header_ash.cc
index e762460..8ee5569a 100644
--- a/chrome/browser/ui/views/frame/browser_frame_header_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_frame_header_ash.cc
@@ -5,13 +5,13 @@
 #include "chrome/browser/ui/views/frame/browser_frame_header_ash.h"
 
 #include "ash/public/cpp/ash_constants.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/public/cpp/frame_utils.h"
 #include "ash/public/cpp/tablet_mode.h"
 #include "base/check.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chromeos/ui/base/window_properties.h"
 #include "chromeos/ui/base/window_state_type.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkPaint.h"
@@ -112,7 +112,7 @@
     views::Widget* target_widget,
     views::View* view,
     AppearanceProvider* appearance_provider,
-    chromeos::FrameCaptionButtonContainerView* caption_button_container)
+    ash::FrameCaptionButtonContainerView* caption_button_container)
     : FrameHeader(target_widget, view) {
   DCHECK(appearance_provider);
   DCHECK(caption_button_container);
diff --git a/chrome/browser/ui/views/frame/browser_frame_header_ash.h b/chrome/browser/ui/views/frame/browser_frame_header_ash.h
index f299ea84..842c76d 100644
--- a/chrome/browser/ui/views/frame/browser_frame_header_ash.h
+++ b/chrome/browser/ui/views/frame/browser_frame_header_ash.h
@@ -31,7 +31,7 @@
       views::Widget* target_widget,
       views::View* view,
       AppearanceProvider* appearance_provider,
-      chromeos::FrameCaptionButtonContainerView* caption_button_container);
+      ash::FrameCaptionButtonContainerView* caption_button_container);
   ~BrowserFrameHeaderAsh() override;
 
   // Returns the amount that the frame background is inset from the left edge of
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
index 7e7e76c2..37cd7ebc 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -7,8 +7,10 @@
 #include <algorithm>
 
 #include "ash/public/cpp/app_types.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/public/cpp/default_frame_header.h"
 #include "ash/public/cpp/frame_utils.h"
+#include "ash/public/cpp/tablet_mode.h"
 #include "ash/public/cpp/window_properties.h"
 #include "ash/wm/window_util.h"
 #include "base/metrics/user_metrics.h"
@@ -38,7 +40,6 @@
 #include "chromeos/ui/base/chromeos_ui_constants.h"
 #include "chromeos/ui/base/window_properties.h"
 #include "chromeos/ui/base/window_state_type.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "content/public/browser/web_contents.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/accessibility/ax_enums.mojom.h"
@@ -94,7 +95,7 @@
 }
 
 BrowserNonClientFrameViewAsh::~BrowserNonClientFrameViewAsh() {
-  chromeos::TabletState::Get()->RemoveObserver(this);
+  ash::TabletMode::Get()->RemoveObserver(this);
 
   ImmersiveModeController* immersive_controller =
       browser_view()->immersive_mode_controller();
@@ -103,8 +104,7 @@
 }
 
 void BrowserNonClientFrameViewAsh::Init() {
-  caption_button_container_ =
-      new chromeos::FrameCaptionButtonContainerView(frame());
+  caption_button_container_ = new ash::FrameCaptionButtonContainerView(frame());
   caption_button_container_->UpdateCaptionButtonState(false /*=animate*/);
   AddChildView(caption_button_container_);
 
@@ -133,7 +133,7 @@
   if (browser->profile()->IsOffTheRecord())
     window->SetProperty(ash::kBlockedForAssistantSnapshotKey, true);
 
-  chromeos::TabletState::Get()->AddObserver(this);
+  ash::TabletMode::Get()->AddObserver(this);
 
   if (frame()->ShouldDrawFrameHeader())
     frame_header_ = CreateFrameHeader();
@@ -414,19 +414,12 @@
                                      : BrowserFrameActiveState::kInactive);
 }
 
-void BrowserNonClientFrameViewAsh::OnTabletStateChanged(
-    chromeos::TabletState::State state) {
-  switch (state) {
-    case chromeos::TabletState::State::kInTabletMode:
-      OnTabletModeToggled(true);
-      return;
-    case chromeos::TabletState::State::kInClamshellMode:
-      OnTabletModeToggled(false);
-      return;
-    case chromeos::TabletState::State::kEnteringTabletMode:
-    case chromeos::TabletState::State::kExitingTabletMode:
-      break;
-  }
+void BrowserNonClientFrameViewAsh::OnTabletModeStarted() {
+  OnTabletModeToggled(true);
+}
+
+void BrowserNonClientFrameViewAsh::OnTabletModeEnded() {
+  OnTabletModeToggled(false);
 }
 
 void BrowserNonClientFrameViewAsh::OnTabletModeToggled(bool enabled) {
@@ -565,7 +558,7 @@
 bool BrowserNonClientFrameViewAsh::ShouldShowCaptionButtonsWhenNotInOverview()
     const {
   return UsePackagedAppHeaderStyle(browser_view()->browser()) ||
-         !chromeos::TabletState::Get()->InTabletMode();
+         !ash::TabletMode::Get()->InTabletMode();
 }
 
 int BrowserNonClientFrameViewAsh::GetToolbarLeftInset() const {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
index a9cca17..f21b1fd3 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "ash/public/cpp/tablet_mode_observer.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -15,7 +16,6 @@
 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 #include "chrome/browser/ui/views/tab_icon_view_model.h"
-#include "chromeos/ui/base/tablet_state.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
 
@@ -26,15 +26,15 @@
 class ProfileIndicatorIcon;
 class TabIconView;
 
-namespace chromeos {
+namespace ash {
 class FrameCaptionButtonContainerView;
-}  // namespace chromeos
+}  // namespace ash
 
 // Provides the BrowserNonClientFrameView for Chrome OS.
 class BrowserNonClientFrameViewAsh
     : public BrowserNonClientFrameView,
       public BrowserFrameHeaderAsh::AppearanceProvider,
-      public chromeos::TabletState::Observer,
+      public ash::TabletModeObserver,
       public TabIconViewModel,
       public aura::WindowObserver,
       public ImmersiveModeController::Observer {
@@ -81,8 +81,9 @@
   int GetFrameHeaderImageYInset() override;
   gfx::ImageSkia GetFrameHeaderOverlayImage(bool active) override;
 
-  // chromeos::TabletState::Observer:
-  void OnTabletStateChanged(chromeos::TabletState::State) override;
+  // ash::TabletModeObserver:
+  void OnTabletModeStarted() override;
+  void OnTabletModeEnded() override;
 
   void OnTabletModeToggled(bool enabled);
 
@@ -201,8 +202,7 @@
   aura::Window* GetFrameWindow();
 
   // View which contains the window controls.
-  chromeos::FrameCaptionButtonContainerView* caption_button_container_ =
-      nullptr;
+  ash::FrameCaptionButtonContainerView* caption_button_container_ = nullptr;
 
   // For popups, the window icon.
   TabIconView* window_icon_ = nullptr;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
index 814bb0b0d..8475d73 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -5,6 +5,7 @@
 #include <string>
 
 #include "ash/public/cpp/ash_switches.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/public/cpp/default_frame_header.h"
 #include "ash/public/cpp/frame_header.h"
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h"
@@ -73,7 +74,6 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "chromeos/ui/base/chromeos_ui_constants.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "components/account_id/account_id.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/keep_alive_registry/keep_alive_types.h"
@@ -462,7 +462,7 @@
       static_cast<BrowserNonClientFrameViewAsh*>(
           widget->non_client_view()->frame_view());
 
-  chromeos::FrameCaptionButtonContainerView::TestApi test(
+  ash::FrameCaptionButtonContainerView::TestApi test(
       frame_view->caption_button_container_);
   EXPECT_TRUE(test.size_button()->icon_definition_for_test());
 }
@@ -1242,7 +1242,7 @@
 IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest,
                        ActiveStateOfButtonMatchesWidget) {
   SetUpWebApp();
-  chromeos::FrameCaptionButtonContainerView::TestApi test(
+  ash::FrameCaptionButtonContainerView::TestApi test(
       GetFrameViewAsh(browser_view_)->caption_button_container_);
   EXPECT_TRUE(test.size_button()->paint_as_active());
   EXPECT_TRUE(GetPaintingAsActive());
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
index 6a3e4574..7ae902e 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.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 "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h"
 #include "ash/public/cpp/test/shell_test_api.h"
 #include "base/macros.h"
@@ -25,7 +26,6 @@
 #include "chrome/common/web_application_info.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "chrome/test/permissions/permission_request_manager_test_api.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/content_mock_cert_verifier.h"
 #include "net/cert/mock_cert_verifier.h"
@@ -272,9 +272,9 @@
   BrowserNonClientFrameViewAsh* frame_view =
       static_cast<BrowserNonClientFrameViewAsh*>(
           browser_view->GetWidget()->non_client_view()->frame_view());
-  chromeos::FrameCaptionButtonContainerView* caption_button_container =
+  ash::FrameCaptionButtonContainerView* caption_button_container =
       frame_view->caption_button_container_;
-  chromeos::FrameCaptionButtonContainerView::TestApi frame_test_api(
+  ash::FrameCaptionButtonContainerView::TestApi frame_test_api(
       caption_button_container);
 
   EXPECT_TRUE(frame_test_api.size_button()->GetVisible());
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
index 08df8c4..f8511346 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
@@ -4,22 +4,47 @@
 
 #include "chrome/browser/ui/views/global_media_controls/media_dialog_view.h"
 
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/global_media_controls/media_notification_service.h"
 #include "chrome/browser/ui/global_media_controls/overlay_media_notification.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/global_media_controls/media_dialog_view_observer.h"
 #include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h"
 #include "chrome/browser/ui/views/global_media_controls/media_notification_list_view.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/sync_preferences/pref_service_syncable.h"
+#include "media/base/media_switches.h"
 #include "services/media_session/public/mojom/media_session.mojom.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/background.h"
 #include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/controls/button/toggle_button.h"
+#include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
+#include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/fill_layout.h"
 
 using media_session::mojom::MediaSessionAction;
 
+namespace {
+
+static constexpr int kLiveCaptionBetweenChildSpacing = 4;
+static constexpr int kLiveCaptionHorizontalMarginDip = 10;
+static constexpr int kLiveCaptionImageWidthDip = 20;
+static constexpr int kLiveCaptionVerticalMarginDip = 16;
+
+}  // namespace
+
 // static
 MediaDialogView* MediaDialogView::instance_ = nullptr;
 
@@ -28,10 +53,11 @@
 
 // static
 views::Widget* MediaDialogView::ShowDialog(views::View* anchor_view,
-                                           MediaNotificationService* service) {
+                                           MediaNotificationService* service,
+                                           Profile* profile) {
   DCHECK(!instance_);
   DCHECK(service);
-  instance_ = new MediaDialogView(anchor_view, service);
+  instance_ = new MediaDialogView(anchor_view, service, profile);
 
   views::Widget* widget =
       views::BubbleDialogDelegateView::CreateBubble(instance_);
@@ -72,7 +98,7 @@
   observed_containers_[id] = container_ptr;
 
   active_sessions_view_->ShowNotification(id, std::move(container));
-  SizeToContents();
+  UpdateBubbleSize();
 
   for (auto& observer : observers_)
     observer.OnMediaSessionShown();
@@ -86,7 +112,7 @@
   if (active_sessions_view_->empty())
     HideDialog();
   else
-    SizeToContents();
+    UpdateBubbleSize();
 
   for (auto& observer : observers_)
     observer.OnMediaSessionHidden();
@@ -113,6 +139,8 @@
 
   SetPaintToLayer();
   layer()->SetRoundedCornerRadius(gfx::RoundedCornersF(corner_radius));
+  if (IsLiveCaptionEnabled())
+    layer()->SetFillsBoundsOpaquely(false);
 
   service_->SetDialogDelegate(this);
 }
@@ -128,8 +156,18 @@
   return gfx::Size(width, 1);
 }
 
-void MediaDialogView::OnContainerSizeChanged() {
+void MediaDialogView::UpdateBubbleSize() {
   SizeToContents();
+  if (!IsLiveCaptionEnabled())
+    return;
+
+  const int width = GetPreferredSize().width();
+  const int height = live_caption_container_->GetPreferredSize().height();
+  live_caption_container_->SetPreferredSize(gfx::Size(width, height));
+}
+
+void MediaDialogView::OnContainerSizeChanged() {
+  UpdateBubbleSize();
 }
 
 void MediaDialogView::OnContainerMetadataChanged() {
@@ -168,10 +206,16 @@
   return active_sessions_view_;
 }
 
+views::Button* MediaDialogView::GetLiveCaptionButtonForTesting() {
+  return live_caption_button_;
+}
+
 MediaDialogView::MediaDialogView(views::View* anchor_view,
-                                 MediaNotificationService* service)
+                                 MediaNotificationService* service,
+                                 Profile* profile)
     : BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
       service_(service),
+      profile_(profile),
       active_sessions_view_(
           AddChildView(std::make_unique<MediaNotificationListView>())) {
   SetButtons(ui::DIALOG_BUTTON_NONE);
@@ -186,8 +230,49 @@
 void MediaDialogView::Init() {
   // Remove margins.
   set_margins(gfx::Insets());
+  if (!IsLiveCaptionEnabled()) {
+    SetLayoutManager(std::make_unique<views::FillLayout>());
+    return;
+  }
+  SetLayoutManager(std::make_unique<views::BoxLayout>(
+                       views::BoxLayout::Orientation::kVertical))
+      ->set_cross_axis_alignment(views::BoxLayout::CrossAxisAlignment::kStart);
 
-  SetLayoutManager(std::make_unique<views::FillLayout>());
+  views::View* live_caption_container = new views::View();
+  auto* live_caption_container_layout =
+      live_caption_container->SetLayoutManager(
+          std::make_unique<views::BoxLayout>(
+              views::BoxLayout::Orientation::kHorizontal,
+              gfx::Insets(kLiveCaptionHorizontalMarginDip,
+                          kLiveCaptionVerticalMarginDip),
+              kLiveCaptionBetweenChildSpacing));
+
+  views::ImageView* live_caption_image = new views::ImageView();
+  live_caption_image->SetImage(
+      gfx::CreateVectorIcon(kLiveCaptionIcon, kLiveCaptionImageWidthDip,
+                            SkColor(gfx::kGoogleGrey700)));
+  views::Label* live_caption_title = new views::Label(
+      l10n_util::GetStringUTF16(IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION));
+  live_caption_title->SetHorizontalAlignment(
+      gfx::HorizontalAlignment::ALIGN_LEFT);
+
+  views::ToggleButton* live_caption_button =
+      new views::ToggleButton(base::BindRepeating(
+          &MediaDialogView::ToggleLiveCaption, base::Unretained(this)));
+  live_caption_button->SetIsOn(
+      profile_->GetPrefs()->GetBoolean(prefs::kLiveCaptionEnabled));
+  live_caption_button->SetAccessibleName(live_caption_title->GetText());
+  live_caption_button->SetThumbOnColor(SkColor(gfx::kGoogleBlue600));
+  live_caption_button->SetTrackOnColor(SkColorSetA(gfx::kGoogleBlue600, 128));
+  live_caption_button->SetThumbOffColor(SK_ColorWHITE);
+  live_caption_button->SetTrackOffColor(SkColor(gfx::kGoogleGrey400));
+
+  live_caption_container->AddChildView(std::move(live_caption_image));
+  live_caption_container_layout->SetFlexForView(
+      live_caption_container->AddChildView(std::move(live_caption_title)), 1);
+  live_caption_button_ =
+      live_caption_container->AddChildView(std::move(live_caption_button));
+  live_caption_container_ = AddChildView(std::move(live_caption_container));
 }
 
 void MediaDialogView::WindowClosing() {
@@ -196,3 +281,13 @@
     service_->SetDialogDelegate(nullptr);
   }
 }
+
+void MediaDialogView::ToggleLiveCaption(const ui::Event& event) {
+  bool enabled = !profile_->GetPrefs()->GetBoolean(prefs::kLiveCaptionEnabled);
+  profile_->GetPrefs()->SetBoolean(prefs::kLiveCaptionEnabled, enabled);
+  live_caption_button_->SetIsOn(enabled);
+}
+
+bool MediaDialogView::IsLiveCaptionEnabled() {
+  return base::FeatureList::IsEnabled(media::kLiveCaption);
+}
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.h b/chrome/browser/ui/views/global_media_controls/media_dialog_view.h
index e3ec2ec..f891a31 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.h
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.h
@@ -5,6 +5,10 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_DIALOG_VIEW_H_
 #define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_DIALOG_VIEW_H_
 
+#include <map>
+#include <memory>
+#include <string>
+
 #include "base/observer_list.h"
 #include "base/optional.h"
 #include "chrome/browser/ui/global_media_controls/media_dialog_delegate.h"
@@ -15,6 +19,11 @@
 class MediaNotificationContainerImplView;
 class MediaNotificationListView;
 class MediaNotificationService;
+class Profile;
+
+namespace views {
+class ToggleButton;
+}
 
 // Dialog that shows media controls that control the active media session.
 class MediaDialogView : public views::BubbleDialogDelegateView,
@@ -22,7 +31,8 @@
                         public MediaNotificationContainerObserver {
  public:
   static views::Widget* ShowDialog(views::View* anchor_view,
-                                   MediaNotificationService* service);
+                                   MediaNotificationService* service,
+                                   Profile* profile);
   static void HideDialog();
   static bool IsShowing();
 
@@ -61,9 +71,12 @@
 
   const MediaNotificationListView* GetListViewForTesting() const;
 
+  views::Button* GetLiveCaptionButtonForTesting();
+
  private:
   explicit MediaDialogView(views::View* anchor_view,
-                           MediaNotificationService* service);
+                           MediaNotificationService* service,
+                           Profile* profile);
   ~MediaDialogView() override;
 
   static MediaDialogView* instance_;
@@ -75,8 +88,16 @@
   void Init() override;
   void WindowClosing() override;
 
+  // views::Button::PressedCallback
+  void ToggleLiveCaption(const ui::Event& event);
+
+  void UpdateBubbleSize();
+  bool IsLiveCaptionEnabled();
+
   MediaNotificationService* const service_;
 
+  Profile* const profile_;
+
   MediaNotificationListView* const active_sessions_view_;
 
   base::ObserverList<MediaDialogViewObserver> observers_;
@@ -85,6 +106,10 @@
   std::map<const std::string, MediaNotificationContainerImplView*>
       observed_containers_;
 
+  views::View* live_caption_container_ = nullptr;
+
+  views::ToggleButton* live_caption_button_ = nullptr;
+
   DISALLOW_COPY_AND_ASSIGN(MediaDialogView);
 };
 
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
index 0519f8d..90cb1535 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/ui/views/global_media_controls/media_notification_list_view.h"
 #include "chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/interactive_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -307,7 +308,9 @@
 
   void SetUp() override {
     feature_list_.InitWithFeatures(
-        {media::kGlobalMediaControls, media::kGlobalMediaControlsForCast}, {});
+        {media::kGlobalMediaControls, media::kGlobalMediaControlsForCast,
+         media::kLiveCaption},
+        {});
 
     presentation_manager_ =
         std::make_unique<TestWebContentsPresentationManager>();
@@ -464,6 +467,14 @@
     ClickButton(GetButtonForAction(MediaSessionAction::kExitPictureInPicture));
   }
 
+  void ClickEnableLiveCaptionOnDialog() {
+    base::RunLoop().RunUntilIdle();
+    ASSERT_TRUE(MediaDialogView::IsShowing());
+    auto* live_caption_button = MediaDialogView::GetDialogViewForTesting()
+                                    ->GetLiveCaptionButtonForTesting();
+    ClickButton(live_caption_button);
+  }
+
   void ClickNotificationByTitle(const base::string16& title) {
     ASSERT_TRUE(MediaDialogView::IsShowing());
     MediaNotificationContainerImplView* notification =
@@ -841,3 +852,37 @@
 
   EXPECT_TRUE(IsPlayingSessionDisplayedFirst());
 }
+
+IN_PROC_BROWSER_TEST_F(MediaDialogViewBrowserTest, LiveCaption) {
+  // Open a tab and play media.
+  OpenTestURL();
+  StartPlayback();
+  WaitForStart();
+
+  // Open the media dialog.
+  WaitForVisibleToolbarIcon();
+  ClickToolbarIcon();
+  WaitForDialogOpened();
+  EXPECT_TRUE(IsDialogVisible());
+
+  ClickEnableLiveCaptionOnDialog();
+  EXPECT_TRUE(
+      browser()->profile()->GetPrefs()->GetBoolean(prefs::kLiveCaptionEnabled));
+
+  ClickEnableLiveCaptionOnDialog();
+  EXPECT_FALSE(
+      browser()->profile()->GetPrefs()->GetBoolean(prefs::kLiveCaptionEnabled));
+
+  // Close dialog and enable live caption preference. Reopen dialog.
+  ClickToolbarIcon();
+  EXPECT_FALSE(IsDialogVisible());
+  browser()->profile()->GetPrefs()->SetBoolean(prefs::kLiveCaptionEnabled,
+                                               true);
+  ClickToolbarIcon();
+  WaitForDialogOpened();
+  EXPECT_TRUE(IsDialogVisible());
+
+  ClickEnableLiveCaptionOnDialog();
+  EXPECT_FALSE(
+      browser()->profile()->GetPrefs()->GetBoolean(prefs::kLiveCaptionEnabled));
+}
diff --git a/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc b/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc
index d48e8d5..ae2756e 100644
--- a/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc
@@ -115,7 +115,7 @@
   if (MediaDialogView::IsShowing()) {
     MediaDialogView::HideDialog();
   } else {
-    MediaDialogView::ShowDialog(this, service_);
+    MediaDialogView::ShowDialog(this, service_, browser_->profile());
 
     feature_promo_controller_->CloseBubble(
         feature_engagement::kIPHLiveCaptionFeature);
diff --git a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
index 1e6cfa47..fa12bc3 100644
--- a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
+++ b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
@@ -64,7 +64,7 @@
     // just doing the same thing here doesn't work.  I suspect that approach
     // will work, though, once the issue causing the blue border is fixed.
     scoped_widget_observer_.Add(
-        MediaDialogView::ShowDialog(media_button, service));
+        MediaDialogView::ShowDialog(media_button, service, profile));
     return true;
   } else {
     // Delegate to the base class, which will show the Cast dialog.
diff --git a/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc b/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
index 9ed8423..884c739a 100644
--- a/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
+++ b/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
@@ -115,7 +115,6 @@
 
   auto dialog_model =
       ui::DialogModel::Builder()
-          .SetShowCloseButton(true)
           .SetTitle(l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_TITLE))
           .AddOkButton(
               base::BindOnce(&OnDialogAccepted, navigator, auto_update_enabled),
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
index ef42644..0ad8af784 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -185,8 +185,6 @@
                              const GURL& url);
   ~InternalPageInfoBubbleView() override;
 
-  gfx::Size CalculatePreferredSize() const override;
-
   DISALLOW_COPY_AND_ASSIGN(InternalPageInfoBubbleView);
 };
 
@@ -398,6 +396,9 @@
       ChromeLayoutProvider::Get()->GetInsetsMetric(views::INSETS_DIALOG));
   set_margins(gfx::Insets());
 
+  SetFixedWidth(ChromeLayoutProvider::Get()->GetDistanceMetric(
+      views::DISTANCE_BUBBLE_PREFERRED_WIDTH));
+
   SetTitle(text);
 
   views::BubbleDialogDelegateView::CreateBubble(this);
@@ -419,20 +420,6 @@
 
 InternalPageInfoBubbleView::~InternalPageInfoBubbleView() {}
 
-gfx::Size InternalPageInfoBubbleView::CalculatePreferredSize() const {
-  // Without a layout manager this will recurse infinitely
-  // (GetHeightForWidth() calls CalculatePreferredSize()).
-  // TODO(crbug.com/1128500): Fix infinite recursion or always
-  // install a layout manager.
-  if (!GetLayoutManager())
-    return gfx::Size();
-
-  const int width = ChromeLayoutProvider::Get()->GetDistanceMetric(
-                        views::DISTANCE_BUBBLE_PREFERRED_WIDTH) -
-                    margins().width();
-  return gfx::Size(width, GetHeightForWidth(width));
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // PageInfoBubbleView
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.cc b/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.cc
index 1aa1593a..b4f5bc98 100644
--- a/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.cc
+++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.cc
@@ -89,6 +89,12 @@
   return entry->GetAvatarIcon(preferred_size);
 }
 
+// TODO(crbug.com/1125474): Replace IsGuest(profile) calls with
+// Profile::IsGuestProfile() after IsEphemeralGuestProfile is fully migrated.
+bool IsGuest(Profile* profile) {
+  return profile->IsGuestSession() || profile->IsEphemeralGuestProfile();
+}
+
 }  // namespace
 
 AvatarToolbarButtonDelegate::AvatarToolbarButtonDelegate() = default;
@@ -161,14 +167,14 @@
 }
 
 int AvatarToolbarButtonDelegate::GetWindowCount() const {
-  if (profile_->IsGuestSession())
+  if (IsGuest(profile_))
     return BrowserList::GetGuestBrowserCount();
   DCHECK(profile_->IsOffTheRecord());
   return BrowserList::GetOffTheRecordBrowsersActiveForProfile(profile_);
 }
 
 AvatarToolbarButton::State AvatarToolbarButtonDelegate::GetState() const {
-  if (profile_->IsGuestSession())
+  if (IsGuest(profile_))
     return AvatarToolbarButton::State::kGuestSession;
 
   // Return |kIncognitoProfile| state for all OffTheRecord profile types except
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.cc b/chrome/browser/ui/views/profiles/profile_menu_view.cc
index c353849..4f52a2f 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view.cc
@@ -153,6 +153,12 @@
          sync_ui_util::AUTH_ERROR;
 }
 
+// TODO(crbug.com/1125474): Replace IsGuest(profile) calls with
+// Profile::IsGuestProfile() after IsEphemeralGuestProfile is fully migrated.
+bool IsGuest(Profile* profile) {
+  return profile->IsGuestSession() || profile->IsEphemeralGuestProfile();
+}
+
 }  // namespace
 
 // ProfileMenuView ---------------------------------------------------------
@@ -171,13 +177,12 @@
 
 void ProfileMenuView::BuildMenu() {
   Profile* profile = browser()->profile();
-  const bool is_guest = profile->IsGuestSession();
-  if (profile->IsRegularProfile()) {
+  if (IsGuest(profile)) {
+    BuildGuestIdentity();
+  } else if (profile->IsRegularProfile()) {
     BuildIdentity();
     BuildSyncInfo();
     BuildAutofillButtons();
-  } else if (is_guest) {
-    BuildGuestIdentity();
   } else {
     NOTREACHED();
   }
@@ -186,7 +191,7 @@
 
 //  ChromeOS doesn't support multi-profile.
 #if !defined(OS_CHROMEOS)
-  if (!(is_guest &&
+  if (!(IsGuest(profile) &&
         base::FeatureList::IsEnabled(features::kNewProfilePicker))) {
     BuildProfileManagementHeading();
     BuildSelectableProfiles();
@@ -580,9 +585,8 @@
   Profile* profile = browser()->profile();
   signin::IdentityManager* identity_manager =
       IdentityManagerFactory::GetForProfile(profile);
-  const bool is_guest = profile->IsGuestSession();
   const bool has_unconsented_account =
-      !is_guest &&
+      !IsGuest(profile) &&
       identity_manager->HasPrimaryAccount(signin::ConsentLevel::kNotRequired);
 
   if (has_unconsented_account && !IsSyncPaused(profile)) {
@@ -606,7 +610,8 @@
   }
 
   int window_count = CountBrowsersFor(profile);
-  if (base::FeatureList::IsEnabled(features::kNewProfilePicker) && is_guest) {
+  if (base::FeatureList::IsEnabled(features::kNewProfilePicker) &&
+      IsGuest(profile)) {
     AddFeatureButton(
         l10n_util::GetPluralStringFUTF16(IDS_GUEST_PROFILE_MENU_CLOSE_BUTTON,
                                          window_count),
@@ -626,7 +631,7 @@
 
 #if !defined(OS_CHROMEOS)
   const bool has_primary_account =
-      !is_guest && identity_manager->HasPrimaryAccount();
+      !IsGuest(profile) && identity_manager->HasPrimaryAccount();
   // The sign-out button is always at the bottom.
   if (has_unconsented_account && !has_primary_account) {
     AddFeatureButton(
@@ -666,7 +671,7 @@
 
   PrefService* service = g_browser_process->local_state();
   DCHECK(service);
-  if (!browser()->profile()->IsGuestSession() &&
+  if (!IsGuest(browser()->profile()) &&
       service->GetBoolean(prefs::kBrowserGuestModeEnabled)) {
     AddSelectableProfile(
         profiles::GetGuestAvatar(),
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.cc b/chrome/browser/ui/views/session_crashed_bubble_view.cc
index 3007cc6..0e3350f 100644
--- a/chrome/browser/ui/views/session_crashed_bubble_view.cc
+++ b/chrome/browser/ui/views/session_crashed_bubble_view.cc
@@ -226,7 +226,7 @@
   SessionCrashedBubbleDelegate* bubble_delegate = bubble_delegate_unique.get();
 
   ui::DialogModel::Builder dialog_builder(std::move(bubble_delegate_unique));
-  dialog_builder.SetShowCloseButton(true)
+  dialog_builder
       .SetTitle(l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_BUBBLE_TITLE))
       .DisableCloseOnDeactivate()
       .SetIsAlertDialog()
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index 30e1c96..cf32c2d 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -634,10 +634,10 @@
     observer.Wait();
   }
 
-  void DragGroupAndNotify(TabStrip* tab_strip,
-                          base::OnceClosure task,
-                          tab_groups::TabGroupId group,
-                          int drag_x_offset = 0) {
+  void DragToDetachGroupAndNotify(TabStrip* tab_strip,
+                                  base::OnceClosure task,
+                                  tab_groups::TabGroupId group,
+                                  int drag_x_offset = 0) {
     test::QuitDraggingObserver observer;
     // Move to the tab and drag it enough so that it detaches.
     const gfx::Point group_header_center =
@@ -2116,10 +2116,10 @@
   StopAnimating(tab_strip2);
 
   // Drag the group by its header into the second browser.
-  DragGroupAndNotify(tab_strip,
-                     base::BindOnce(&DragAllToSeparateWindowStep2, this,
-                                    tab_strip, tab_strip2),
-                     group);
+  DragToDetachGroupAndNotify(tab_strip,
+                             base::BindOnce(&DragAllToSeparateWindowStep2, this,
+                                            tab_strip, tab_strip2),
+                             group);
   ASSERT_TRUE(ReleaseInput());
 
   // Expect the group to be in browser2, but with a new tab_groups::TabGroupId.
@@ -2233,9 +2233,9 @@
   StopAnimating(tab_strip);
   EnsureFocusToTabStrip(tab_strip);
 
-  DragGroupAndNotify(tab_strip,
-                     base::BindOnce(&PressEscapeWhileDetachedHeaderStep2, this),
-                     group);
+  DragToDetachGroupAndNotify(
+      tab_strip, base::BindOnce(&PressEscapeWhileDetachedHeaderStep2, this),
+      group);
 
   EXPECT_FALSE(tab_strip->group_header(group)->dragging());
 
@@ -2349,9 +2349,9 @@
   StopAnimating(tab_strip);
   EXPECT_TRUE(model->IsGroupCollapsed(group));
 
-  DragGroupAndNotify(tab_strip,
-                     base::BindOnce(&PressEscapeWhileDetachedHeaderStep2, this),
-                     group);
+  DragToDetachGroupAndNotify(
+      tab_strip, base::BindOnce(&PressEscapeWhileDetachedHeaderStep2, this),
+      group);
 
   EXPECT_FALSE(tab_strip->group_header(group)->dragging());
   ASSERT_FALSE(tab_strip->GetDragContext()->IsDragSessionActive());
@@ -2366,110 +2366,36 @@
   EXPECT_TRUE(tab_strip->controller()->IsGroupCollapsed(group));
 }
 
-// Creates a browser with four tabs. The first two belong in Tab Group 1, and
-// the last two belong in Tab Group 2. Dragging the collapsed group header of
-// Tab Group 1 right will result in Tab Group 1 moving but avoiding Tab Group 2.
+// Creates a browser with four tabs. The first two tabs belong in Tab Group 1.
+// Dragging the collapsed group header of Tab Group 1 will result in Tab Group 1
+// expanding.
 IN_PROC_BROWSER_TEST_P(
     DetachToBrowserTabDragControllerTestWithTabGroupsCollapseEnabled,
-    DragCollapsedGroupHeaderRightAvoidsOtherGroups) {
+    DragCollapsedGroupHeaderExpandsGroup) {
   TabStrip* tab_strip = GetTabStripForBrowser(browser());
   TabStripModel* model = browser()->tab_strip_model();
   TabGroupModel* group_model = model->group_model();
 
   AddTabsAndResetBrowser(browser(), 3);
-  tab_groups::TabGroupId group1 = model->AddToNewGroup({0, 1});
-  EXPECT_FALSE(model->IsGroupCollapsed(group1));
-  tab_strip->controller()->ToggleTabGroupCollapsedState(group1);
+  tab_groups::TabGroupId group = model->AddToNewGroup({2, 3});
+  ASSERT_FALSE(model->IsGroupCollapsed(group));
+  tab_strip->controller()->ToggleTabGroupCollapsedState(group);
   StopAnimating(tab_strip);
-  EXPECT_TRUE(model->IsGroupCollapsed(group1));
-  tab_groups::TabGroupId group2 = model->AddToNewGroup({2, 3});
-  StopAnimating(tab_strip);
+  ASSERT_TRUE(model->IsGroupCollapsed(group));
+  EnsureFocusToTabStrip(tab_strip);
 
   ASSERT_EQ(4, model->count());
-  ASSERT_EQ(2u, group_model->GetTabGroup(group1)->ListTabs().size());
-  ASSERT_EQ(2u, group_model->GetTabGroup(group2)->ListTabs().size());
+  ASSERT_EQ(2u, group_model->GetTabGroup(group)->ListTabs().size());
 
-  // Drag group1 right, but not far enough to get to the other side of group2.
-  ASSERT_TRUE(PressInput(
-      GetCenterInScreenCoordinates(tab_strip->group_header(group1))));
-  ASSERT_TRUE(DragInputTo(GetCenterInScreenCoordinates(tab_strip->tab_at(0))));
-  ASSERT_TRUE(ReleaseInput());
-  StopAnimating(tab_strip);
-
-  // Expect group1 to "snap back" to its current position, avoiding group2.
-  EXPECT_EQ("0 1 2 3", IDString(model));
-  EXPECT_THAT(group_model->GetTabGroup(group1)->ListTabs(),
-              testing::ElementsAre(0, 1));
-  EXPECT_THAT(group_model->GetTabGroup(group2)->ListTabs(),
-              testing::ElementsAre(2, 3));
-
-  // Drag group1 right, far enough to get to the other side of group2.
-  ASSERT_TRUE(PressInput(
-      GetCenterInScreenCoordinates(tab_strip->group_header(group1))));
+  // Drag group1, this should expand the group.
+  ASSERT_TRUE(
+      PressInput(GetCenterInScreenCoordinates(tab_strip->group_header(group))));
   ASSERT_TRUE(DragInputTo(GetCenterInScreenCoordinates(tab_strip->tab_at(1))));
+  ASSERT_TRUE(TabDragController::IsActive());
+  EXPECT_FALSE(model->IsGroupCollapsed(group));
   ASSERT_TRUE(ReleaseInput());
   StopAnimating(tab_strip);
-
-  // Expect group1 to "snap to" the other side of group2 and not land in the
-  // middle.
-  EXPECT_EQ("2 3 0 1", IDString(model));
-  EXPECT_THAT(group_model->GetTabGroup(group1)->ListTabs(),
-              testing::ElementsAre(2, 3));
-  EXPECT_THAT(group_model->GetTabGroup(group2)->ListTabs(),
-              testing::ElementsAre(0, 1));
-}
-
-// Creates a browser with four tabs. The first two belong in Tab Group 1, and
-// the last two belong in Tab Group 2. Dragging the collapsed group header of
-// Tab Group 2 left will result in Tab Group 2 moving but avoiding Tab Group 1.
-IN_PROC_BROWSER_TEST_P(
-    DetachToBrowserTabDragControllerTestWithTabGroupsCollapseEnabled,
-    DragCollapsedGroupHeaderLeftAvoidsOtherGroups) {
-  TabStrip* tab_strip = GetTabStripForBrowser(browser());
-  TabStripModel* model = browser()->tab_strip_model();
-  TabGroupModel* group_model = model->group_model();
-
-  AddTabsAndResetBrowser(browser(), 3);
-  tab_groups::TabGroupId group1 = model->AddToNewGroup({0, 1});
-  tab_groups::TabGroupId group2 = model->AddToNewGroup({2, 3});
-
-  EXPECT_FALSE(model->IsGroupCollapsed(group2));
-  tab_strip->controller()->ToggleTabGroupCollapsedState(group2);
-  StopAnimating(tab_strip);
-  EXPECT_TRUE(model->IsGroupCollapsed(group2));
-
-  ASSERT_EQ(4, model->count());
-  ASSERT_EQ(2u, group_model->GetTabGroup(group1)->ListTabs().size());
-  ASSERT_EQ(2u, group_model->GetTabGroup(group2)->ListTabs().size());
-
-  // Drag group2 left, but not far enough to get to the other side of group1.
-  ASSERT_TRUE(PressInput(
-      GetCenterInScreenCoordinates(tab_strip->group_header(group2))));
-  ASSERT_TRUE(DragInputTo(GetCenterInScreenCoordinates(tab_strip->tab_at(1))));
-  ASSERT_TRUE(ReleaseInput());
-  StopAnimating(tab_strip);
-
-  // Expect group2 to "snap back" to its current position, avoiding group1.
-  EXPECT_EQ("0 1 2 3", IDString(model));
-  EXPECT_THAT(group_model->GetTabGroup(group1)->ListTabs(),
-              testing::ElementsAre(0, 1));
-  EXPECT_THAT(group_model->GetTabGroup(group2)->ListTabs(),
-              testing::ElementsAre(2, 3));
-
-  // Drag group2 left, far enough to get to the other side of group1.
-  ASSERT_TRUE(PressInput(
-      GetCenterInScreenCoordinates(tab_strip->group_header(group2))));
-  ASSERT_TRUE(DragInputTo(GetCenterInScreenCoordinates(tab_strip->tab_at(0))));
-  ASSERT_TRUE(ReleaseInput());
-  StopAnimating(tab_strip);
-
-  // Expect group2 to "snap to" the other side of group1 and not land in the
-  // middle.
-  EXPECT_EQ("2 3 0 1", IDString(model));
-  EXPECT_THAT(group_model->GetTabGroup(group1)->ListTabs(),
-              testing::ElementsAre(2, 3));
-  EXPECT_THAT(group_model->GetTabGroup(group2)->ListTabs(),
-              testing::ElementsAre(0, 1));
+  EXPECT_FALSE(model->IsGroupCollapsed(group));
 }
 
 // Creates two browsers, then drags a collapsed group from one to the other.
@@ -2492,7 +2418,7 @@
   StopAnimating(tab_strip2);
 
   // Drag the group by its header into the second browser.
-  DragGroupAndNotify(
+  DragToDetachGroupAndNotify(
       tab_strip,
       base::BindOnce(&DragToSeparateWindowStep2, this, tab_strip, tab_strip2),
       group);
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc
index 91f2cd08..93c38ae 100644
--- a/chrome/browser/ui/webui/extensions/extensions_ui.cc
+++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -67,18 +67,9 @@
                                                    bool in_dev_mode) {
   content::WebUIDataSource* source =
       content::WebUIDataSource::Create(chrome::kChromeUIExtensionsHost);
-#if BUILDFLAG(OPTIMIZE_WEBUI)
-  webui::SetupBundledWebUIDataSource(source, "extensions.js",
-                                     IDR_EXTENSIONS_EXTENSIONS_ROLLUP_JS,
-                                     IDR_EXTENSIONS_EXTENSIONS_HTML);
-  source->AddResourcePath("checkup_image.svg", IDR_EXTENSIONS_CHECKUP_IMAGE);
-  source->AddResourcePath("checkup_image_dark.svg",
-                          IDR_EXTENSIONS_CHECKUP_IMAGE_DARK);
-#else
   webui::SetupWebUIDataSource(
       source, base::make_span(kExtensionsResources, kExtensionsResourcesSize),
       "", IDR_EXTENSIONS_EXTENSIONS_HTML);
-#endif
 
   static constexpr webui::LocalizedString kLocalizedStrings[] = {
     // Add common strings.
diff --git a/chrome/browser/ui/webui/media/media_engagement_ui.cc b/chrome/browser/ui/webui/media/media_engagement_ui.cc
index 7031f4e..2c74904 100644
--- a/chrome/browser/ui/webui/media/media_engagement_ui.cc
+++ b/chrome/browser/ui/webui/media/media_engagement_ui.cc
@@ -29,6 +29,7 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
+#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h"
 
 #if !defined(OS_ANDROID)
 #include "chrome/common/pref_names.h"
@@ -95,11 +96,11 @@
     switch (web_ui_->GetWebContents()
                 ->GetOrCreateWebPreferences()
                 .autoplay_policy) {
-      case blink::web_pref::AutoplayPolicy::kNoUserGestureRequired:
+      case blink::mojom::AutoplayPolicy::kNoUserGestureRequired:
         return "no-user-gesture-required";
-      case blink::web_pref::AutoplayPolicy::kUserGestureRequired:
+      case blink::mojom::AutoplayPolicy::kUserGestureRequired:
         return "user-gesture-required";
-      case blink::web_pref::AutoplayPolicy::kDocumentUserActivationRequired:
+      case blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired:
         return "document-user-activation-required";
     }
   }
diff --git a/chrome/browser/vr/DEPS b/chrome/browser/vr/DEPS
index 5a96fc1..3bb3bf60 100644
--- a/chrome/browser/vr/DEPS
+++ b/chrome/browser/vr/DEPS
@@ -4,6 +4,7 @@
   "+cc/test",
   "+cc/trees",
   "+chrome/android/features/vr/jni_headers",
+  "+components/webxr",
   "+device/vr",
 ]
 
diff --git a/chrome/browser/vr/chrome_xr_integration_client.cc b/chrome/browser/vr/chrome_xr_integration_client.cc
index 395a823..4e5bf60 100644
--- a/chrome/browser/vr/chrome_xr_integration_client.cc
+++ b/chrome/browser/vr/chrome_xr_integration_client.cc
@@ -23,13 +23,34 @@
 #include "chrome/browser/android/vr/gvr_install_helper.h"
 #include "device/vr/android/gvr/gvr_device_provider.h"
 #if BUILDFLAG(ENABLE_ARCORE)
-#include "chrome/browser/android/vr/chrome_arcore_install_helper.h"
+#include "chrome/browser/infobars/infobar_service.h"
+#include "components/webxr/android/arcore_install_helper.h"
+#include "components/webxr/android/xr_install_helper_delegate.h"
 #include "device/vr/android/arcore/arcore_device_provider_factory.h"
 #endif  // ENABLE_ARCORE
 #endif  // OS_WIN/OS_ANDROID
 
 namespace vr {
 
+// Note that this doesn't technically need to be behind this buildflag, but
+// ArCore is the only thing that's using it right now.
+#if BUILDFLAG(ENABLE_ARCORE)
+class ChromeXrInstallHelperDelegate : public webxr::XrInstallHelperDelegate {
+ public:
+  ChromeXrInstallHelperDelegate() = default;
+  ~ChromeXrInstallHelperDelegate() override = default;
+
+  ChromeXrInstallHelperDelegate(const ChromeXrInstallHelperDelegate&) = delete;
+  ChromeXrInstallHelperDelegate& operator=(
+      const ChromeXrInstallHelperDelegate&) = delete;
+
+  infobars::InfoBarManager* GetInfoBarManager(
+      content::WebContents* web_contents) override {
+    return InfoBarService::FromWebContents(web_contents);
+  }
+};
+#endif
+
 std::unique_ptr<content::XrInstallHelper>
 ChromeXrIntegrationClient::GetInstallHelper(
     device::mojom::XRDeviceId device_id) {
@@ -39,7 +60,8 @@
       return std::make_unique<GvrInstallHelper>();
 #if BUILDFLAG(ENABLE_ARCORE)
     case device::mojom::XRDeviceId::ARCORE_DEVICE_ID:
-      return std::make_unique<ChromeArCoreInstallHelper>();
+      return std::make_unique<webxr::ArCoreInstallHelper>(
+          std::make_unique<ChromeXrInstallHelperDelegate>());
 #endif  // ENABLE_ARCORE
 #endif  // OS_ANDROID
     default:
diff --git a/chrome/browser/web_applications/system_web_app_manager_browsertest.cc b/chrome/browser/web_applications/system_web_app_manager_browsertest.cc
index a77aee9..f7fa661 100644
--- a/chrome/browser/web_applications/system_web_app_manager_browsertest.cc
+++ b/chrome/browser/web_applications/system_web_app_manager_browsertest.cc
@@ -222,14 +222,6 @@
       registrar.FindAppWithUrlInScope(content::GetWebUIURL("test-system-app/")),
       app_id);
 
-  if (!base::FeatureList::IsEnabled(features::kDesktopPWAsWithoutExtensions)) {
-    const extensions::Extension* extension =
-        extensions::ExtensionRegistry::Get(profile)->GetInstalledExtension(
-            app_id);
-    EXPECT_TRUE(extension->from_bookmark());
-    EXPECT_EQ(extensions::Manifest::EXTERNAL_COMPONENT, extension->location());
-  }
-
   // OS Integration only relevant for Chrome OS.
 #if defined(OS_CHROMEOS)
   apps::AppServiceProxy* proxy = GetAppServiceProxy(browser()->profile());
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 4774df4f..99ce52a 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-master-1602525418-afe56390c440c08698d6b71f1c497e873e6a051a.profdata
+chrome-linux-master-1602546992-ba4d1f5ead4061da7fd3853f89c3c9703bc786ae.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index b60a9e2..f484bf5 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1602525418-295b1a16e5c5eb1a611980e5afdf689a2be9286a.profdata
+chrome-mac-master-1602546992-4541e834d35741f8358d6360b79d19523776e3ad.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index e8085e7..51fde2b 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-master-1602435952-232be9ce3683aa917ade383918bb42eb3e64b0d9.profdata
+chrome-win32-master-1602514791-92b25c346599f1253fe4b5957e8929536703cfb0.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index d385559..1c121c9 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1602503558-c2e745b5a37c8ee5f138ede7ee7fff767428f64a.profdata
+chrome-win64-master-1602536311-64e797cbe41fbbe11cccf8259e756a8b7f11c663.profdata
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index 242df9c..4de7967 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -346,6 +346,9 @@
 const char kEasyUnlockLearnMoreUrl[] =
     "https://support.google.com/chromebook/?p=smart_lock";
 
+const char kEchoLearnMoreURL[] =
+    "chrome://help-app/help/sub/3399709/id/2703646";
+
 const char kArcTermsPathFormat[] = "arc_tos/%s/terms.html";
 
 const char kArcPrivacyPolicyPathFormat[] = "arc_tos/%s/privacy_policy.pdf";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index 6e09be3..1901783 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -304,6 +304,9 @@
 // The URL for the "Learn more" link the the Easy Unlock settings.
 extern const char kEasyUnlockLearnMoreUrl[];
 
+// The URL for the help center article about redeeming Chromebook offers.
+extern const char kEchoLearnMoreURL[];
+
 // The URL for EOL notification
 extern const char kEolNotificationURL[];
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 2b444000..0267292d 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2006,6 +2006,7 @@
         "../browser/extensions/identifiability_metrics_test_util.cc",
         "../browser/extensions/identifiability_metrics_test_util.h",
         "../browser/extensions/isolated_app_browsertest.cc",
+        "../browser/extensions/isolated_world_csp_browsertest.cc",
         "../browser/extensions/lazy_background_page_apitest.cc",
         "../browser/extensions/lazy_background_page_test_util.h",
         "../browser/extensions/manifest_v3_browsertest.cc",
@@ -2393,7 +2394,6 @@
         "../browser/chromeos/file_manager/audio_player_browsertest.cc",
         "../browser/chromeos/file_manager/devtools_listener.cc",
         "../browser/chromeos/file_manager/devtools_listener.h",
-        "../browser/chromeos/file_manager/devtools_listener_browsertest.cc",
         "../browser/chromeos/file_manager/external_filesystem_apitest.cc",
         "../browser/chromeos/file_manager/file_manager_base_jstest.cc",
         "../browser/chromeos/file_manager/file_manager_browsertest.cc",
diff --git a/chrome/test/data/extensions/api_test/isolated_world_csp/mv2/eval.js b/chrome/test/data/extensions/api_test/isolated_world_csp/mv2/eval.js
new file mode 100644
index 0000000..df6a0d7
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world_csp/mv2/eval.js
@@ -0,0 +1,10 @@
+// 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.
+
+chrome.test.runTests([function testEval() {
+  window.foo = 2;
+  eval('window.foo = 3;');
+  chrome.test.assertEq(3, window.foo);
+  chrome.test.succeed();
+}]);
diff --git a/chrome/test/data/extensions/api_test/isolated_world_csp/mv2/javascript_url.js b/chrome/test/data/extensions/api_test/isolated_world_csp/mv2/javascript_url.js
new file mode 100644
index 0000000..6b3922da
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world_csp/mv2/javascript_url.js
@@ -0,0 +1,14 @@
+// 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.
+
+const button = document.createElement('button');
+button.id = 'my-button';
+
+// DOM Property event handlers execute in the world they are registered in.
+button.onclick = () => {
+  chrome.test.notifyPass();
+};
+document.body.appendChild(button);
+
+location.href = 'javascript:document.getElementById("my-button").click();';
diff --git a/chrome/test/data/extensions/api_test/isolated_world_csp/mv2/manifest.json b/chrome/test/data/extensions/api_test/isolated_world_csp/mv2/manifest.json
new file mode 100644
index 0000000..6a45091
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world_csp/mv2/manifest.json
@@ -0,0 +1,19 @@
+{
+  "name": "MV2: Bypass main world CSP in isolated worlds.",
+  "manifest_version": 2,
+  "version": "1.0",
+  "content_scripts": [
+    {
+      "matches": ["*://eval.com/*"],
+      "js": ["eval.js"]
+    },
+    {
+      "matches": ["*://js-url.com/*"],
+      "js": ["javascript_url.js"]
+    },
+    {
+      "matches": ["*://remote-script.com/*"],
+      "js": ["remote_script.js"]
+    }
+  ]
+}
diff --git a/chrome/test/data/extensions/api_test/isolated_world_csp/mv2/remote_script.js b/chrome/test/data/extensions/api_test/isolated_world_csp/mv2/remote_script.js
new file mode 100644
index 0000000..f4458e2
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world_csp/mv2/remote_script.js
@@ -0,0 +1,19 @@
+// 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.
+
+chrome.test.getConfig(config => {
+  chrome.test.runTests([function testRemoteScript() {
+    let port = config.testServer.port;
+    let script = document.createElement('script');
+    script.src = `http://google.com:${port}/script.js`;
+    script.onload = () => {
+      chrome.test.assertEq('New Title', document.title);
+      chrome.test.succeed();
+    };
+    script.onerror = () => {
+      chrome.test.fail('Script load failed unexpectedly');
+    };
+    document.body.appendChild(script);
+  }]);
+});
diff --git a/chrome/test/data/extensions/api_test/isolated_world_csp/mv3/eval.js b/chrome/test/data/extensions/api_test/isolated_world_csp/mv3/eval.js
new file mode 100644
index 0000000..6a54701
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world_csp/mv3/eval.js
@@ -0,0 +1,14 @@
+// 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.
+
+chrome.test.runTests([function testEval() {
+  window.foo = 2;
+  var exceptedExceptionMessage = 'Refused to evaluate a string as JavaScript ' +
+      'because \'unsafe-eval\' is not an allowed source of script in the ' +
+      'following Content Security Policy directive: "script-src \'self\'"';
+  chrome.test.assertThrows(
+      eval, ['window.foo = 3;'], new RegExp(exceptedExceptionMessage));
+  chrome.test.assertEq(2, window.foo);
+  chrome.test.succeed();
+}]);
diff --git a/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event_init.idl b/chrome/test/data/extensions/api_test/isolated_world_csp/mv3/javascript_url.js
similarity index 61%
rename from third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event_init.idl
rename to chrome/test/data/extensions/api_test/isolated_world_csp/mv3/javascript_url.js
index 87c91987..e543e1f 100644
--- a/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event_init.idl
+++ b/chrome/test/data/extensions/api_test/isolated_world_csp/mv3/javascript_url.js
@@ -2,6 +2,5 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-dictionary VirtualKeyboardGeometryChangeEventInit : EventInit {
-    required DOMRect boundingRect;
-};
+location.href = 'javascript:document.title="New Title";';
+chrome.test.notifyPass();
diff --git a/chrome/test/data/extensions/api_test/isolated_world_csp/mv3/manifest.json b/chrome/test/data/extensions/api_test/isolated_world_csp/mv3/manifest.json
new file mode 100644
index 0000000..8e2c87ab
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world_csp/mv3/manifest.json
@@ -0,0 +1,19 @@
+{
+  "name": "MV3: Strict isolated world CSP.",
+  "manifest_version": 3,
+  "version": "1.0",
+  "content_scripts": [
+    {
+      "matches": ["*://eval.com/*"],
+      "js": ["eval.js"]
+    },
+    {
+      "matches": ["*://js-url.com/*"],
+      "js": ["javascript_url.js"]
+    },
+    {
+      "matches": ["*://remote-script.com/*"],
+      "js": ["remote_script.js"]
+    }
+  ]
+}
diff --git a/chrome/test/data/extensions/api_test/isolated_world_csp/mv3/remote_script.js b/chrome/test/data/extensions/api_test/isolated_world_csp/mv3/remote_script.js
new file mode 100644
index 0000000..562eb48
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world_csp/mv3/remote_script.js
@@ -0,0 +1,18 @@
+// 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.
+
+chrome.test.getConfig(config => {
+  let port = config.testServer.port;
+
+  let script = document.createElement('script');
+  script.src = `http://example.com:${port}/script.js`;
+  script.onload = () => {
+    chrome.test.notifyFail('Script load succeeded unexpectedly');
+  };
+  script.onerror = () => {
+    chrome.test.notifyPass();
+  };
+
+  document.body.appendChild(script);
+});
diff --git a/chrome/test/data/extensions/api_test/isolated_world_csp/page_with_script_src_csp.html b/chrome/test/data/extensions/api_test/isolated_world_csp/page_with_script_src_csp.html
new file mode 100644
index 0000000..5ec028e
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/isolated_world_csp/page_with_script_src_csp.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<meta http-equiv="Content-Security-Policy" content="script-src http://example.com:*;">
+<title>Page With CSP</title>
diff --git a/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event_init.idl b/chrome/test/data/extensions/api_test/isolated_world_csp/script.js
similarity index 61%
copy from third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event_init.idl
copy to chrome/test/data/extensions/api_test/isolated_world_csp/script.js
index 87c91987..65cb79bf 100644
--- a/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event_init.idl
+++ b/chrome/test/data/extensions/api_test/isolated_world_csp/script.js
@@ -2,6 +2,4 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-dictionary VirtualKeyboardGeometryChangeEventInit : EventInit {
-    required DOMRect boundingRect;
-};
+document.title = 'New Title';
diff --git a/chrome/test/data/subresource_filter/popup.html b/chrome/test/data/subresource_filter/popup.html
new file mode 100644
index 0000000..70652de
--- /dev/null
+++ b/chrome/test/data/subresource_filter/popup.html
@@ -0,0 +1,5 @@
+<html>
+  <body>
+    <img src='/subresource_filter/pixel.png?ad=true' onload='document.title = "loaded";' onerror='document.title = "failed";'>
+  </body>
+</html>
\ No newline at end of file
diff --git a/chrome/test/data/subresource_filter/popup_disallowed_load_helper.html b/chrome/test/data/subresource_filter/popup_disallowed_load_helper.html
new file mode 100644
index 0000000..7c3d6ff
--- /dev/null
+++ b/chrome/test/data/subresource_filter/popup_disallowed_load_helper.html
@@ -0,0 +1,31 @@
+<html>
+  <head><script>
+    function popupLoadsDisallowedResource(popup_url) {
+      popup = window.open(popup_url);
+      doc = popup.document;
+      doc.open();
+      doc.write(
+        "<html><body>Rewritten. <img src='/ad_tagging/pixel.png?ad=true' " +
+        "onload='window.document.title = \"loaded\";' " +
+        "onerror='window.document.title = \"failed\";'></body></html>");
+      doc.close();
+    }
+    function popupLoadsDisallowedResourceAsDescendant(popup_url) {
+      popup = window.open(popup_url);
+      doc = popup.document;
+      doc.open();
+      doc.write(
+          "<html><head><script>" +
+          "function onLoadHandler() {" +
+          "  iframe = document.getElementById('child');" +
+          "  if (iframe.contentDocument) {" +
+          "     window.document.title = 'loaded';" +
+          "  } else {" +
+          "     window.document.title = 'failed';" +
+          "  }}</scr" + "ipt></head>" +
+          "<body>Rewritten. <iframe id='child' src='/empty.html?ad=true' " +
+          "onload='onLoadHandler();'></body></html>");
+      doc.close();
+    }
+  </script></head>
+</html>
\ No newline at end of file
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js
index 377ffac..63f26eb 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js
@@ -21,6 +21,7 @@
  ['FakeMojoInterface', 'diagnostics/mojo_interface_provider_test.js'],
  ['FakeSystemDataProvider', 'diagnostics/fake_system_data_provider_test.js'],
  ['FakeMethodProvider', 'diagnostics/fake_method_provider_test.js'],
+ ['RoutineListExecutor', 'diagnostics/routine_list_executor_test.js'],
  ['RoutineResultEntry', 'diagnostics/routine_result_entry_test.js'],
  ['RoutineResultList', 'diagnostics/routine_result_list_test.js'],
  ['RoutineSection', 'diagnostics/routine_section_test.js'],
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_list_executor_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_list_executor_test.js
new file mode 100644
index 0000000..50f7670
--- /dev/null
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_list_executor_test.js
@@ -0,0 +1,118 @@
+// 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.
+
+// TODO(jimmyxgong): Use es6 module for mojo binding (crbug/1004256).
+import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+
+import {RoutineName, RoutineResultInfo, StandardRoutineResult} from 'chrome://diagnostics/diagnostics_types.js';
+import {FakeSystemRoutineController} from 'chrome://diagnostics/fake_system_routine_controller.js';
+import {ExecutionProgress, ResultStatusItem, RoutineListExecutor} from 'chrome://diagnostics/routine_list_executor.js';
+
+suite('FakeRoutineListExecutorTest', () => {
+  /** @type {?FakeSystemRoutineController} */
+  let controller = null;
+
+  /** @type {?RoutineListExecutor} */
+  let executor = null;
+
+  setup(() => {
+    controller = new FakeSystemRoutineController();
+    executor = new RoutineListExecutor(controller);
+  });
+
+  teardown(() => {
+    controller = null;
+    executor = null;
+  });
+
+  /**
+   * Helper function that takes an array of RoutineResultInfo which contains
+   * the routine name and expected result, initializes the fake routine runner,
+   * then executes and validates the results.
+   * @param {!Array<!RoutineResultInfo>} routines
+   */
+  function runRoutinesAndAssertResults(routines) {
+    let expectedCallbacks = [];
+    let routineNames = [];
+    routines.forEach((routine) => {
+      // Set the result into the fake.
+      assertNotEquals(undefined, routine);
+      assertNotEquals(undefined, routine.result);
+      assertNotEquals(undefined, routine.result.simple_result);
+      controller.setFakeStandardRoutineResult(
+          routine.name, routine.result.simple_result);
+
+      // Build the list of routines to run.
+      routineNames.push(routine.name);
+
+      // Add the "running" callback to the list.
+      let status = new ResultStatusItem(routine.name);
+      status.progress = ExecutionProgress.kRunning;
+      expectedCallbacks.push(status);
+
+      // Add the "completed" callback to the list.
+      status = new ResultStatusItem(routine.name);
+      status.progress = ExecutionProgress.kCompleted;
+      status.result = routine.result;
+      expectedCallbacks.push(status);
+    });
+
+    // Create the callback that validates the arguments.
+    let upto = 0;
+
+    /** @type {!function(!ResultStatusItem)} */
+    let statusCallback = (status) => {
+      assertTrue(upto < expectedCallbacks.length);
+      assertEquals(expectedCallbacks[upto].name, status.name);
+      assertEquals(expectedCallbacks[upto].progress, status.progress);
+      if (status.progress === ExecutionProgress.kRunning) {
+        assertEquals(null, status.result);
+      } else {
+        assertEquals(
+            expectedCallbacks[upto].result.simple_result,
+            status.result.simple_result);
+      }
+
+      upto++;
+    };
+
+    return executor.runRoutines(routineNames, statusCallback).then(() => {
+      // Ensure that all the callbacks were sent.
+      assertEquals(expectedCallbacks.length, upto);
+    });
+  }
+
+  test('SingleTest', () => {
+    /** @type {!Array<!RoutineResultInfo>} */
+    const routines = [{
+      name: RoutineName.kCpuStress,
+      result: {simple_result: StandardRoutineResult.kTestFailed}
+    }];
+    return runRoutinesAndAssertResults(routines);
+  });
+
+  test('MultipleTests', () => {
+    /** @type {!Array<!RoutineResultInfo>} */
+    const routines = [
+      {
+        name: RoutineName.kCpuStress,
+        result: {simple_result: StandardRoutineResult.kTestPassed}
+      },
+      {
+        name: RoutineName.kCpuCache,
+        result: {simple_result: StandardRoutineResult.kTestFailed}
+      },
+      {
+        name: RoutineName.kFloatingPoint,
+        result: {simple_result: StandardRoutineResult.kTestPassed}
+      },
+      {
+        name: RoutineName.kPrimeSearch,
+        result: {simple_result: StandardRoutineResult.kTestFailed}
+      }
+    ];
+
+    return runRoutinesAndAssertResults(routines);
+  });
+});
diff --git a/chrome/tools/build/mac/infoplist_strings_util.mm b/chrome/tools/build/mac/infoplist_strings_util.mm
index 85b3833..5a25e36 100644
--- a/chrome/tools/build/mac/infoplist_strings_util.mm
+++ b/chrome/tools/build/mac/infoplist_strings_util.mm
@@ -266,10 +266,12 @@
       NSDictionary<NSString*, NSString*>* infoplist_strings = @{
         @"CFBundleGetInfoString" : get_info,
         @"NSHumanReadableCopyright" : copyright,
+
+        @"NSBluetoothAlwaysUsageDescription" : permission_reason,
+        @"NSBluetoothPeripheralUsageDescription" : permission_reason,
+        @"NSCameraUsageDescription" : permission_reason,
         @"NSLocationUsageDescription" : permission_reason,
         @"NSMicrophoneUsageDescription" : permission_reason,
-        @"NSCameraUsageDescription" : permission_reason,
-        @"NSBluetoothPeripheralUsageDescription" : permission_reason,
       };
       base::scoped_nsobject<NSMutableString> strings_file_contents_string(
           [[NSMutableString alloc] init]);
diff --git a/chromecast/browser/cast_web_preferences.h b/chromecast/browser/cast_web_preferences.h
index fc5a21d..a3487f5 100644
--- a/chromecast/browser/cast_web_preferences.h
+++ b/chromecast/browser/cast_web_preferences.h
@@ -7,7 +7,7 @@
 
 #include <base/optional.h>
 #include <base/supports_user_data.h>
-#include <third_party/blink/public/common/web_preferences/web_preferences.h>
+#include <third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h>
 
 namespace chromecast {
 
@@ -18,7 +18,7 @@
   struct Preferences {
     Preferences();
 
-    base::Optional<blink::web_pref::AutoplayPolicy> autoplay_policy;
+    base::Optional<blink::mojom::AutoplayPolicy> autoplay_policy;
     base::Optional<bool> hide_scrollbars;
     base::Optional<bool> javascript_enabled;
   };
diff --git a/chromecast/browser/webview/webview_controller.cc b/chromecast/browser/webview/webview_controller.cc
index 656ba2c..d82258d 100644
--- a/chromecast/browser/webview/webview_controller.cc
+++ b/chromecast/browser/webview/webview_controller.cc
@@ -23,7 +23,6 @@
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
-#include "third_party/blink/public/common/web_preferences/autoplay_policy.h"
 
 namespace chromecast {
 
@@ -197,8 +196,8 @@
 
   cast_prefs->preferences()->autoplay_policy =
       request.require_user_gesture()
-          ? blink::web_pref::AutoplayPolicy::kUserGestureRequired
-          : blink::web_pref::AutoplayPolicy::kNoUserGestureRequired;
+          ? blink::mojom::AutoplayPolicy::kUserGestureRequired
+          : blink::mojom::AutoplayPolicy::kNoUserGestureRequired;
   UpdateWebkitPreferences(contents, cast_prefs);
 }
 
diff --git a/chromeos/audio/audio_device.cc b/chromeos/audio/audio_device.cc
index c0e3c60..a95a2f2d 100644
--- a/chromeos/audio/audio_device.cc
+++ b/chromeos/audio/audio_device.cc
@@ -18,19 +18,11 @@
 // Get the priority for a particular device type. The priority returned
 // will be between 0 to 3, the higher number meaning a higher priority.
 uint8_t GetDevicePriority(AudioDeviceType type, bool is_input) {
-  // Lower the priority of bluetooth wide band mic. Although the quality is
-  // better than narrow band(AUDIO_TYPE_BLUETOOTH_NB_MIC), we still want
-  // to avoid auto-selecting Bluetooth mic when there is another audio input
-  // option.
-  if (type == AUDIO_TYPE_BLUETOOTH && is_input)
-    return 0;
   switch (type) {
     case AUDIO_TYPE_HEADPHONE:
     case AUDIO_TYPE_LINEOUT:
     case AUDIO_TYPE_MIC:
     case AUDIO_TYPE_USB:
-    // This is for bluetooth output node. Bluetooth inputs(wide band and narrow
-    // band mic) are handled separately.
     case AUDIO_TYPE_BLUETOOTH:
       return 3;
     case AUDIO_TYPE_HDMI:
diff --git a/chromeos/components/diagnostics_ui/resources/BUILD.gn b/chromeos/components/diagnostics_ui/resources/BUILD.gn
index 9a2f480..6979d18 100644
--- a/chromeos/components/diagnostics_ui/resources/BUILD.gn
+++ b/chromeos/components/diagnostics_ui/resources/BUILD.gn
@@ -26,6 +26,7 @@
     ":overview_card",
     ":percent_bar_chart",
     ":realtime_cpu_chart",
+    ":routine_list_executor",
     ":routine_result_entry",
     ":routine_result_list",
     ":routine_section",
@@ -136,6 +137,10 @@
   ]
 }
 
+js_library("routine_list_executor") {
+  deps = [ "//ui/webui/resources/js:cr.m" ]
+}
+
 js_library("routine_result_entry") {
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
diff --git a/chromeos/components/diagnostics_ui/resources/diagnostics_app_resources.grd b/chromeos/components/diagnostics_ui/resources/diagnostics_app_resources.grd
index 76978d01..5c8ee20 100644
--- a/chromeos/components/diagnostics_ui/resources/diagnostics_app_resources.grd
+++ b/chromeos/components/diagnostics_ui/resources/diagnostics_app_resources.grd
@@ -31,6 +31,7 @@
       <include name="IDR_DIAGNOSTICS_OVERVIEW_CARD_JS" file="${root_gen_dir}/chromeos/components/diagnostics_ui/resources/overview_card.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_DIAGNOSTICS_PERCENT_BAR_CHART_JS" file="${root_gen_dir}/chromeos/components/diagnostics_ui/resources/percent_bar_chart.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_DIAGNOSTICS_REALTIME_CPU_CHART_JS" file="${root_gen_dir}/chromeos/components/diagnostics_ui/resources/realtime_cpu_chart.js" use_base_dir="false" type="BINDATA"/>
+      <include name="IDR_DIAGNOSTICS_ROUTINE_LIST_EXECUTOR_JS" file="routine_list_executor.js" type="BINDATA"/>
       <include name="IDR_DIAGNOSTICS_ROUTINE_RESULT_ENTRY_JS" file="${root_gen_dir}/chromeos/components/diagnostics_ui/resources/routine_result_entry.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_DIAGNOSTICS_ROUTINE_RESULT_LIST_JS" file="${root_gen_dir}/chromeos/components/diagnostics_ui/resources/routine_result_list.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_DIAGNOSTICS_ROUTINE_SECTION_JS" file="${root_gen_dir}/chromeos/components/diagnostics_ui/resources/routine_section.js" use_base_dir="false" type="BINDATA"/>
diff --git a/chromeos/components/diagnostics_ui/resources/routine_list_executor.js b/chromeos/components/diagnostics_ui/resources/routine_list_executor.js
new file mode 100644
index 0000000..badf689
--- /dev/null
+++ b/chromeos/components/diagnostics_ui/resources/routine_list_executor.js
@@ -0,0 +1,119 @@
+// 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 {assert} from 'chrome://resources/js/assert.m.js';
+import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';
+import {RoutineName, RoutineResult, RoutineResultInfo, SystemRoutineControllerInterface} from './diagnostics_types.js';
+
+/**
+ * Represents the execution progress of a test routine.
+ * @enum {number}
+ */
+export let ExecutionProgress = {
+  kNotStarted: 0,
+  kRunning: 1,
+  kCompleted: 2,
+  kCancelled: 3,
+};
+
+/**
+ * Represents the input to a single routine-result-entry in a
+ * routine-result-list.
+ */
+export class ResultStatusItem {
+  constructor(routine) {
+    /** @type {!RoutineName} */
+    this.routine = routine;
+
+    /** @type {!ExecutionProgress} */
+    this.progress = ExecutionProgress.kNotStarted;
+
+    /** @type {?RoutineResult} */
+    this.result = null;
+  }
+};
+
+/**
+ * The type of the status callback function.
+ * @typedef {!function(!ResultStatusItem)}
+ */
+export let StatusCallbackFunction;
+
+/**
+ * Implements the RoutineRunner remote. Creates a resolver and resolves it when
+ * the onRoutineResult function is called.
+ */
+class ExecutionContext {
+  constructor() {
+    /** @private {!PromiseResolver} */
+    this.resolver_ = new PromiseResolver();
+  }
+
+  /**
+   * Implements RoutineRunner.onRoutineResult.
+   * @param {!RoutineResultInfo} result
+   **/
+  onRoutineResult(result) {
+    this.resolver_.resolve(result);
+  }
+
+  whenComplete() {
+    return this.resolver_.promise;
+  }
+}
+
+/**
+ * Executes a list of test routines, firing a status callback with a
+ * ResultStatusItem before and after each test. The resulting ResultStatusItem
+ * maps directly to an entry in a routine-result-list.
+ */
+export class RoutineListExecutor {
+  /**
+   * @param {!SystemRoutineControllerInterface} routineController
+   */
+  constructor(routineController) {
+    /** @private {!SystemRoutineControllerInterface} */
+    this.routineController_ = routineController;
+  }
+
+  /*
+   * Executes a list of routines providing a status callback as each test
+   * starts and finishes. The return promise will resolve when all tests are
+   * completed.
+   * @param {!Array<!RoutineName>} routines
+   * @type {!function(!ResultStatusItem)} statusCallback
+   * @param {!Promise}
+   */
+  runRoutines(routines, statusCallback) {
+    assert(routines.length > 0);
+
+    // Create a chain of promises that each schedule the next routine when
+    // they complete, firing the status callback before and after each test.
+    let promise = Promise.resolve();
+    routines.forEach((name) => {
+      promise = promise.then(() => {
+        // Notify the status callback that a test started running.
+        const status = new ResultStatusItem(name);
+        status.progress = ExecutionProgress.kRunning;
+        statusCallback(status);
+
+        // Create a new remote and execute the next test.
+        let test = new ExecutionContext();
+        return this.routineController_.runRoutine(name, test).then(() => {
+          // When the test completes, notify the status callback of the
+          // result.
+          return test.whenComplete().then((info) => {
+            assert(info.name === name);
+            const status = new ResultStatusItem(name);
+            status.progress = ExecutionProgress.kCompleted;
+            status.result = info.result;
+            statusCallback(status);
+          });
+        });
+      });
+    });
+
+    return promise;
+  }
+}
diff --git a/chromeos/crosapi/cpp/bitmap_util.cc b/chromeos/crosapi/cpp/bitmap_util.cc
index cbdad346..7f3c2b2b 100644
--- a/chromeos/crosapi/cpp/bitmap_util.cc
+++ b/chromeos/crosapi/cpp/bitmap_util.cc
@@ -4,16 +4,13 @@
 
 #include "chromeos/crosapi/cpp/bitmap_util.h"
 
-#include <algorithm>
 #include <vector>
 
-#include "base/check.h"
 #include "base/check_op.h"
 #include "base/numerics/checked_math.h"
 #include "base/numerics/safe_conversions.h"
 #include "chromeos/crosapi/cpp/bitmap.h"
 #include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkImageInfo.h"
 
 namespace crosapi {
 
@@ -33,17 +30,4 @@
   return snapshot;
 }
 
-SkBitmap SkBitmapFromBitmap(const Bitmap& snapshot) {
-  SkImageInfo info =
-      SkImageInfo::Make(snapshot.width, snapshot.height, kBGRA_8888_SkColorType,
-                        kPremul_SkAlphaType);
-  CHECK_EQ(info.computeByteSize(info.minRowBytes()), snapshot.pixels.size());
-  SkBitmap sk_bitmap;
-  CHECK(sk_bitmap.tryAllocPixels(info));
-  std::copy(snapshot.pixels.begin(), snapshot.pixels.end(),
-            static_cast<uint8_t*>(sk_bitmap.getPixels()));
-  sk_bitmap.notifyPixelsChanged();
-  return sk_bitmap;
-}
-
 }  // namespace crosapi
diff --git a/chromeos/crosapi/cpp/bitmap_util.h b/chromeos/crosapi/cpp/bitmap_util.h
index aef4074..bcd2443 100644
--- a/chromeos/crosapi/cpp/bitmap_util.h
+++ b/chromeos/crosapi/cpp/bitmap_util.h
@@ -18,11 +18,6 @@
 // invalid size (e.g. its size is not equal to width * height * 4).
 COMPONENT_EXPORT(CROSAPI) Bitmap BitmapFromSkBitmap(const SkBitmap& sk_bitmap);
 
-// Converts a crosapi::Bitmap to an SkBitmap. Assumes the bitmap is 8-bit
-// ARGB with premultiplied alpha.
-// TODO(https://crbug.com/1116652): Support more flexible image options.
-COMPONENT_EXPORT(CROSAPI) SkBitmap SkBitmapFromBitmap(const Bitmap& bitmap);
-
 }  // namespace crosapi
 
 #endif  // CHROMEOS_CROSAPI_CPP_BITMAP_UTIL_H_
diff --git a/chromeos/network/portal_detector/mock_network_portal_detector.h b/chromeos/network/portal_detector/mock_network_portal_detector.h
index c84a3c2c..8a2d4ab1 100644
--- a/chromeos/network/portal_detector/mock_network_portal_detector.h
+++ b/chromeos/network/portal_detector/mock_network_portal_detector.h
@@ -26,7 +26,7 @@
                    const std::string& service_path));
   MOCK_METHOD0(IsEnabled, bool());
   MOCK_METHOD1(Enable, void(bool start_detection));
-  MOCK_METHOD1(StartPortalDetection, bool(bool force));
+  MOCK_METHOD0(StartPortalDetection, void());
   MOCK_METHOD1(SetStrategy,
                void(chromeos::PortalDetectorStrategy::StrategyId id));
 
diff --git a/chromeos/network/portal_detector/network_portal_detector.h b/chromeos/network/portal_detector/network_portal_detector.h
index 8dae139..5a83828 100644
--- a/chromeos/network/portal_detector/network_portal_detector.h
+++ b/chromeos/network/portal_detector/network_portal_detector.h
@@ -97,10 +97,9 @@
   virtual void Enable(bool start_detection) = 0;
 
   // Starts or restarts portal detection for the default network. If not
-  // currently in the idle state, does nothing unless |force| is true in which
-  // case any current detection is stopped and a new attempt is started. Returns
-  // true if a new portal detection attempt was started.
-  virtual bool StartPortalDetection(bool force) = 0;
+  // currently in the idle state, does nothing. Returns true if a new portal
+  // detection attempt was started.
+  virtual void StartPortalDetection() = 0;
 
   // Sets current strategy according to |id|. If current detection id
   // doesn't equal to |id|, detection is restarted.
diff --git a/chromeos/network/portal_detector/network_portal_detector_stub.cc b/chromeos/network/portal_detector/network_portal_detector_stub.cc
index bbeffda..cdbd34b7 100644
--- a/chromeos/network/portal_detector/network_portal_detector_stub.cc
+++ b/chromeos/network/portal_detector/network_portal_detector_stub.cc
@@ -31,9 +31,7 @@
 
 void NetworkPortalDetectorStub::Enable(bool start_detection) {}
 
-bool NetworkPortalDetectorStub::StartPortalDetection(bool force) {
-  return false;
-}
+void NetworkPortalDetectorStub::StartPortalDetection() {}
 
 void NetworkPortalDetectorStub::SetStrategy(
     PortalDetectorStrategy::StrategyId id) {}
diff --git a/chromeos/network/portal_detector/network_portal_detector_stub.h b/chromeos/network/portal_detector/network_portal_detector_stub.h
index b3f54e81..057e5b5 100644
--- a/chromeos/network/portal_detector/network_portal_detector_stub.h
+++ b/chromeos/network/portal_detector/network_portal_detector_stub.h
@@ -25,7 +25,7 @@
       const std::string& service_path) override;
   bool IsEnabled() override;
   void Enable(bool start_detection) override;
-  bool StartPortalDetection(bool force) override;
+  void StartPortalDetection() override;
   void SetStrategy(PortalDetectorStrategy::StrategyId id) override;
 
   DISALLOW_COPY_AND_ASSIGN(NetworkPortalDetectorStub);
diff --git a/chromeos/ui/base/tablet_state.cc b/chromeos/ui/base/tablet_state.cc
index b4cde3e..c657002 100644
--- a/chromeos/ui/base/tablet_state.cc
+++ b/chromeos/ui/base/tablet_state.cc
@@ -26,24 +26,9 @@
   g_instance = nullptr;
 }
 
-void TabletState::AddObserver(Observer* observer) {
-  observers_.AddObserver(observer);
-}
-
-void TabletState::RemoveObserver(Observer* observer) {
-  observers_.RemoveObserver(observer);
-}
-
 bool TabletState::InTabletMode() const {
   return state_ == TabletState::kInTabletMode ||
          state_ == TabletState::kEnteringTabletMode;
 }
 
-void TabletState::SetState(State state) {
-  state_ = state;
-
-  for (auto& observer : observers_)
-    observer.OnTabletStateChanged(state_);
-}
-
 }  // namespace chromeos
diff --git a/chromeos/ui/base/tablet_state.h b/chromeos/ui/base/tablet_state.h
index b14ca62..b3176c6 100644
--- a/chromeos/ui/base/tablet_state.h
+++ b/chromeos/ui/base/tablet_state.h
@@ -6,7 +6,6 @@
 #define CHROMEOS_UI_BASE_TABLET_STATE_H_
 
 #include "base/component_export.h"
-#include "base/observer_list.h"
 
 namespace ash {
 class TabletModeController;
@@ -32,21 +31,12 @@
     kExitingTabletMode,
   };
 
-  class COMPONENT_EXPORT(CHROMEOS_UI_BASE) Observer {
-   public:
-    virtual void OnTabletStateChanged(State state) = 0;
-
-   protected:
-    virtual ~Observer() = default;
-  };
-
   TabletState();
   TabletState(const TabletState&) = delete;
   TabletState& operator=(const TabletState&) = delete;
   ~TabletState();
 
-  void AddObserver(Observer* observer);
-  void RemoveObserver(Observer* observer);
+  // TODO(http://crbug.com/1113900): Introduce Add|RemoveObserver support.
 
   // Returns true if the system is in tablet mode.
   bool InTabletMode() const;
@@ -58,9 +48,7 @@
   // the tablet state.
   friend class ash::TabletModeController;
 
-  void SetState(State state);
-
-  base::ObserverList<Observer>::Unchecked observers_;
+  void SetState(State state) { state_ = state; }
 
   State state_ = State::kInClamshellMode;
 };
diff --git a/chromeos/ui/frame/BUILD.gn b/chromeos/ui/frame/BUILD.gn
deleted file mode 100644
index 6ccf190..0000000
--- a/chromeos/ui/frame/BUILD.gn
+++ /dev/null
@@ -1,35 +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.
-
-assert(is_chromeos || is_lacros,
-       "Non-Chrome-OS or Lacros builds must not depend on //chromeos")
-
-# C++ headers and sources that can be used by both ash and lacros builds.
-source_set("frame") {
-  defines = [ "IS_CHROMEOS_UI_FRAME" ]
-
-  sources = [
-    "caption_buttons/caption_button_model.h",
-    "caption_buttons/frame_back_button.cc",
-    "caption_buttons/frame_back_button.h",
-    "caption_buttons/frame_caption_button_container_view.cc",
-    "caption_buttons/frame_caption_button_container_view.h",
-    "caption_buttons/frame_size_button.cc",
-    "caption_buttons/frame_size_button.h",
-    "caption_buttons/frame_size_button_delegate.h",
-    "caption_buttons/snap_controller.cc",
-    "caption_buttons/snap_controller.h",
-  ]
-
-  deps = [
-    "//base",
-    "//chromeos/ui/base",
-    "//chromeos/ui/vector_icons",
-    "//skia",
-    "//ui/aura",
-    "//ui/base",
-    "//ui/strings:ui_strings_grit",
-    "//ui/views",
-  ]
-}
diff --git a/chromeos/ui/frame/DEPS b/chromeos/ui/frame/DEPS
deleted file mode 100644
index b2b9550..0000000
--- a/chromeos/ui/frame/DEPS
+++ /dev/null
@@ -1,10 +0,0 @@
-include_rules = [
-  "+ui/aura",
-  "+ui/base",
-  "+ui/compositor/scoped_animation_duration_scale_mode.h",
-  "+ui/events/event_sink.h",
-  "+ui/gfx",
-  "+ui/strings/grit/ui_strings.h",
-  "+ui/views",
-  "+third_party/skia",
-]
diff --git a/chromeos/ui/frame/caption_buttons/frame_back_button.h b/chromeos/ui/frame/caption_buttons/frame_back_button.h
deleted file mode 100644
index 331de34..0000000
--- a/chromeos/ui/frame/caption_buttons/frame_back_button.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2017 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 CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_BACK_BUTTON_H_
-#define CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_BACK_BUTTON_H_
-
-#include "base/component_export.h"
-#include "ui/views/window/frame_caption_button.h"
-
-namespace chromeos {
-
-// A button to send back key events. It's used in Chrome hosted app windows,
-// among other places.
-class COMPONENT_EXPORT(CHROMEOS_UI_FRAME) FrameBackButton
-    : public views::FrameCaptionButton,
-      public views::ButtonListener {
- public:
-  FrameBackButton();
-  ~FrameBackButton() override;
-
-  // views::ButtonListener:
-  void ButtonPressed(Button* sender, const ui::Event& event) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(FrameBackButton);
-};
-
-}  // namespace chromeos
-
-#endif  //  CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_BACK_BUTTON_H_
diff --git a/components/arc/enterprise/arc_data_snapshotd_manager.cc b/components/arc/enterprise/arc_data_snapshotd_manager.cc
index 0a331788..c20c173d 100644
--- a/components/arc/enterprise/arc_data_snapshotd_manager.cc
+++ b/components/arc/enterprise/arc_data_snapshotd_manager.cc
@@ -11,15 +11,12 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
-#include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
 #include "components/arc/arc_prefs.h"
 #include "components/arc/enterprise/arc_data_snapshotd_bridge.h"
 #include "components/prefs/pref_service.h"
-#include "components/session_manager/core/session_manager.h"
-#include "components/user_manager/user_manager.h"
 #include "ui/ozone/public/ozone_switches.h"
 
 namespace arc {
@@ -37,7 +34,7 @@
 constexpr char kPrevious[] = "previous";
 constexpr char kLast[] = "last";
 constexpr char kBlockedUiReboot[] = "blocked_ui_reboot";
-constexpr char kStarted[] = "started";
+constexpr char kStartedDate[] = "started_date";
 
 bool IsSnapshotEnabled() {
   // TODO(pbond): implement policy processing.
@@ -62,9 +59,6 @@
 
 bool ArcDataSnapshotdManager::is_snapshot_enabled_for_testing_ = false;
 
-// This class is owned by ChromeBrowserMainPartsChromeos.
-static ArcDataSnapshotdManager* g_arc_data_snapshotd_manager = nullptr;
-
 ArcDataSnapshotdManager::SnapshotInfo::SnapshotInfo(const base::Value* value,
                                                     bool last)
     : is_last_(last) {
@@ -159,11 +153,11 @@
 ArcDataSnapshotdManager::Snapshot::CreateForTesting(
     PrefService* local_state,
     bool blocked_ui_mode,
-    bool started,
+    const std::string& started_date,
     std::unique_ptr<SnapshotInfo> last,
     std::unique_ptr<SnapshotInfo> previous) {
   return base::WrapUnique(new ArcDataSnapshotdManager::Snapshot(
-      local_state, blocked_ui_mode, started, std::move(last),
+      local_state, blocked_ui_mode, started_date, std::move(last),
       std::move(previous)));
 }
 
@@ -188,9 +182,9 @@
       blocked_ui_mode_ = found.value();
   }
   {
-    auto found = dict->FindBoolPath(kStarted);
-    if (found.has_value())
-      started_ = found.value();
+    auto* found = dict->FindStringPath(kStartedDate);
+    if (found)
+      started_date_ = *found;
   }
 }
 
@@ -201,7 +195,7 @@
   if (last_)
     last_->Sync(&dict);
   dict.SetBoolKey(kBlockedUiReboot, blocked_ui_mode_);
-  dict.SetBoolKey(kStarted, started_);
+  dict.SetStringKey(kStartedDate, started_date_);
   local_state_->Set(arc::prefs::kArcSnapshotInfo, std::move(dict));
 }
 
@@ -211,42 +205,23 @@
   Sync();
 }
 
-void ArcDataSnapshotdManager::Snapshot::StartNewSnapshot() {
-  previous_ = std::move(last_);
-  last_ = nullptr;
-
-  started_ = true;
-  Sync();
-}
-
 ArcDataSnapshotdManager::Snapshot::Snapshot(
     PrefService* local_state,
     bool blocked_ui_mode,
-    bool started,
+    const std::string& started_date,
     std::unique_ptr<SnapshotInfo> last,
     std::unique_ptr<SnapshotInfo> previous)
     : local_state_(local_state),
       blocked_ui_mode_(blocked_ui_mode),
-      started_(started),
+      started_date_(started_date),
       last_(std::move(last)),
       previous_(std::move(previous)) {
   DCHECK(local_state_);
 }
 
-// static
-ArcDataSnapshotdManager* ArcDataSnapshotdManager::Get() {
-  return g_arc_data_snapshotd_manager;
-}
-
-ArcDataSnapshotdManager::ArcDataSnapshotdManager(
-    PrefService* local_state,
-    base::OnceClosure attempt_user_exit_callback)
-    : snapshot_{local_state},
-      attempt_user_exit_callback_(std::move(attempt_user_exit_callback)) {
-  DCHECK(!g_arc_data_snapshotd_manager);
+ArcDataSnapshotdManager::ArcDataSnapshotdManager(PrefService* local_state)
+    : snapshot_{local_state} {
   DCHECK(local_state);
-  g_arc_data_snapshotd_manager = this;
-
   snapshot_.Parse();
 
   if (IsRestoredSession()) {
@@ -262,11 +237,6 @@
 }
 
 ArcDataSnapshotdManager::~ArcDataSnapshotdManager() {
-  DCHECK(g_arc_data_snapshotd_manager);
-  g_arc_data_snapshotd_manager = nullptr;
-
-  session_manager::SessionManager::Get()->RemoveObserver(this);
-
   snapshot_.Sync();
   EnsureDaemonStopped(base::DoNothing());
 }
@@ -291,37 +261,6 @@
   StopDaemon(std::move(callback));
 }
 
-bool ArcDataSnapshotdManager::IsAutoLoginConfigured() {
-  switch (state_) {
-    case ArcDataSnapshotdManager::State::kBlockedUi:
-    case ArcDataSnapshotdManager::State::kMgsToLaunch:
-    case ArcDataSnapshotdManager::State::kMgsLaunched:
-      return true;
-    case ArcDataSnapshotdManager::State::kNone:
-    case ArcDataSnapshotdManager::State::kRestored:
-      return false;
-  }
-}
-
-bool ArcDataSnapshotdManager::IsAutoLoginAllowed() {
-  switch (state_) {
-    case ArcDataSnapshotdManager::State::kBlockedUi:
-      return false;
-    case ArcDataSnapshotdManager::State::kNone:
-    case ArcDataSnapshotdManager::State::kRestored:
-    case ArcDataSnapshotdManager::State::kMgsLaunched:
-    case ArcDataSnapshotdManager::State::kMgsToLaunch:
-      return true;
-  }
-}
-
-void ArcDataSnapshotdManager::OnSessionStateChanged() {
-  if (state_ != State::kMgsToLaunch)
-    return;
-  if (user_manager::UserManager::Get()->IsLoggedInAsPublicAccount())
-    state_ = State::kMgsLaunched;
-}
-
 void ArcDataSnapshotdManager::StopDaemon(base::OnceClosure callback) {
   VLOG(1) << "Stopping arc-data-snapshotd";
   daemon_weak_ptr_factory_.InvalidateWeakPtrs();
@@ -392,22 +331,10 @@
 
 void ArcDataSnapshotdManager::OnKeyPairGenerated(bool success) {
   if (success) {
-    VLOG(1) << "Managed Guest Session is ready to be started with blocked UI.";
     state_ = State::kMgsToLaunch;
-    session_manager::SessionManager::Get()->AddObserver(this);
-    // Move last to previous snapshot:
-    snapshot_.StartNewSnapshot();
-
-    if (!reset_autologin_callback_.is_null())
-      std::move(reset_autologin_callback_).Run();
   } else {
+    // TODO(pbond): restart browser to normal.
     LOG(ERROR) << "Key pair generation failed. Abort snapshot creation.";
-
-    snapshot_.set_blocked_ui_mode(false);
-    snapshot_.Sync();
-
-    DCHECK(!attempt_user_exit_callback_.is_null());
-    EnsureDaemonStopped(std::move(attempt_user_exit_callback_));
   }
 }
 
diff --git a/components/arc/enterprise/arc_data_snapshotd_manager.h b/components/arc/enterprise/arc_data_snapshotd_manager.h
index aba4e15a..4dec658 100644
--- a/components/arc/enterprise/arc_data_snapshotd_manager.h
+++ b/components/arc/enterprise/arc_data_snapshotd_manager.h
@@ -10,7 +10,6 @@
 
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
-#include "components/session_manager/core/session_manager_observer.h"
 
 class PrefService;
 
@@ -27,8 +26,7 @@
 
 // This class manages ARC data/ directory snapshots and controls the lifetime of
 // the arc-data-snapshotd daemon.
-class ArcDataSnapshotdManager final
-    : public session_manager::SessionManagerObserver {
+class ArcDataSnapshotdManager final {
  public:
   // State of the flow.
   enum class State {
@@ -111,7 +109,7 @@
     static std::unique_ptr<Snapshot> CreateForTesting(
         PrefService* local_state,
         bool blocked_ui_mode,
-        bool started,
+        const std::string& started_date,
         std::unique_ptr<SnapshotInfo> last,
         std::unique_ptr<SnapshotInfo> previous);
 
@@ -123,22 +121,14 @@
     // if |last| is true or previous otherwise.
     void ClearSnapshot(bool last);
 
-    // Moves last snapshot to previous and updates a |start_date| to the current
-    // date.
-    void StartNewSnapshot();
-
-    void set_blocked_ui_mode(bool blocked_ui_mode) {
-      blocked_ui_mode_ = blocked_ui_mode;
-    }
     bool is_blocked_ui_mode() const { return blocked_ui_mode_; }
-    bool started() const { return started_; }
     SnapshotInfo* last() { return last_.get(); }
     SnapshotInfo* previous() { return previous_.get(); }
 
    private:
     Snapshot(PrefService* local_state,
              bool blocked_ui_mode,
-             bool started,
+             const std::string& started_date,
              std::unique_ptr<SnapshotInfo> last,
              std::unique_ptr<SnapshotInfo> previous);
 
@@ -148,49 +138,32 @@
     // Values should be kept in sync with values stored in arc.snapshot
     // preference.
     bool blocked_ui_mode_ = false;
-    bool started_;
+    std::string started_date_;
     std::unique_ptr<SnapshotInfo> last_;
     std::unique_ptr<SnapshotInfo> previous_;
   };
 
-  ArcDataSnapshotdManager(PrefService* local_state,
-                          base::OnceClosure attempt_user_exit_callback);
+  explicit ArcDataSnapshotdManager(PrefService* local_state);
   ArcDataSnapshotdManager(const ArcDataSnapshotdManager&) = delete;
   ArcDataSnapshotdManager& operator=(const ArcDataSnapshotdManager&) = delete;
-  ~ArcDataSnapshotdManager() override;
-
-  static ArcDataSnapshotdManager* Get();
+  ~ArcDataSnapshotdManager();
 
   // Starts arc-data-snapshotd.
   void EnsureDaemonStarted(base::OnceClosure callback);
   // Stops arc-data-snapshotd.
   void EnsureDaemonStopped(base::OnceClosure callback);
 
-  // Returns true if autologin to public account should be performed.
-  bool IsAutoLoginConfigured();
-  // Returns true if autologin is allowed to be performed and manager is not
-  // waiting for the response from arc-data-snapshotd daemon.
-  bool IsAutoLoginAllowed();
-
-  // session_manager::SessionManagerObserver:
-  void OnSessionStateChanged() override;
-
   // Get |bridge_| for testing.
   ArcDataSnapshotdBridge* bridge() { return bridge_.get(); }
 
   State state() const { return state_; }
 
-  void set_reset_autologin_callback(base::OnceClosure callback) {
-    reset_autologin_callback_ = std::move(callback);
-  }
-
   static void set_snapshot_enabled_for_testing(bool enabled) {
     is_snapshot_enabled_for_testing_ = enabled;
   }
   static bool is_snapshot_enabled_for_testing() {
     return is_snapshot_enabled_for_testing_;
   }
-  void set_state_for_testing(State state) { state_ = state; }
 
  private:
   // Attempts to arc-data-snapshotd daemon regardless of state of the class.
@@ -228,11 +201,6 @@
 
   std::unique_ptr<ArcDataSnapshotdBridge> bridge_;
 
-  base::OnceClosure attempt_user_exit_callback_;
-
-  // Callback to reset an autologin timer once userless MGS is ready to start.
-  base::OnceClosure reset_autologin_callback_;
-
   // Used for cancelling previously posted tasks to daemon.
   base::WeakPtrFactory<ArcDataSnapshotdManager> daemon_weak_ptr_factory_{this};
   // WeakPtrFactory to use for callbacks.
diff --git a/components/arc/enterprise/arc_data_snapshotd_manager_unittest.cc b/components/arc/enterprise/arc_data_snapshotd_manager_unittest.cc
index 5b172890..d645161 100644
--- a/components/arc/enterprise/arc_data_snapshotd_manager_unittest.cc
+++ b/components/arc/enterprise/arc_data_snapshotd_manager_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
-#include "base/test/bind_test_util.h"
 #include "base/test/task_environment.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/arc/fake_arc_data_snapshotd_client.h"
@@ -18,7 +17,6 @@
 #include "components/arc/arc_prefs.h"
 #include "components/arc/enterprise/arc_data_snapshotd_bridge.h"
 #include "components/prefs/testing_pref_service.h"
-#include "components/session_manager/core/session_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/ozone/public/ozone_switches.h"
@@ -105,7 +103,6 @@
  private:
   TestingPrefServiceSimple local_state_;
   std::unique_ptr<TestUpstartClient> upstart_client_;
-  session_manager::SessionManager session_manager_;
 };
 
 // Tests flows in ArcDataSnapshotdManager:
@@ -128,9 +125,7 @@
   }
 
   // Check number of snapshots in local_state.
-  void CheckSnapshots(int expected_snapshots_number,
-                      bool expected_blocked_ui = true,
-                      bool expected_snapshot_started = false) {
+  void CheckSnapshotsNumber(int expected_number) {
     ArcDataSnapshotdManager::Snapshot snapshot(local_state());
     snapshot.Parse();
     int actual_number = 0;
@@ -140,14 +135,12 @@
     if (snapshot.last()) {
       actual_number++;
     }
-    EXPECT_EQ(expected_snapshots_number, actual_number);
-    EXPECT_EQ(expected_blocked_ui, snapshot.is_blocked_ui_mode());
-    EXPECT_EQ(expected_snapshot_started, snapshot.started());
+    EXPECT_EQ(expected_number, actual_number);
   }
 
   // Set up local_state with info for previous and last snapshots and blocked ui
   // mode.
-  void SetupLocalState(bool blocked_ui_mode) {
+  void SetupLocalState() {
     auto last = ArcDataSnapshotdManager::SnapshotInfo::CreateForTesting(
         "" /* os_version */, "" /* creation_date */, false /* verified */,
         false /* updated */, true /* last */);
@@ -155,16 +148,11 @@
         "" /* os_version */, "" /* creation_date */, false /* verified */,
         false /* updated */, false /* last */);
     auto snapshot = ArcDataSnapshotdManager::Snapshot::CreateForTesting(
-        local_state(), blocked_ui_mode, false /* started */, std::move(last),
-        std::move(previous));
+        local_state(), true /* blocked_ui_mode */, "" /* started_date */,
+        std::move(last), std::move(previous));
     snapshot->Sync();
   }
 
-  void TearDownLocalState() {
-    ArcDataSnapshotdManager::Snapshot snapshot(local_state());
-    snapshot.Sync();
-  }
-
   void RunUntilIdle() {
     if (is_dbus_client_available()) {
       task_environment_.RunUntilIdle();
@@ -182,9 +170,7 @@
 
 // Test basic scenario: start / stop arc-data-snapshotd.
 TEST_F(ArcDataSnapshotdManagerBasicTest, Basic) {
-  // Daemon stopped in ctor, since no need to be running.
-  ExpectStopDaemon(false /* success */);
-  ArcDataSnapshotdManager manager(local_state(), base::DoNothing());
+  ArcDataSnapshotdManager manager(local_state());
   EXPECT_EQ(manager.state(), ArcDataSnapshotdManager::State::kNone);
   EXPECT_FALSE(manager.bridge());
 
@@ -200,9 +186,7 @@
 // Test a double start scenario: start arc-data-snapshotd twice.
 // Upstart job returns "false" if the job is already running.
 TEST_F(ArcDataSnapshotdManagerBasicTest, DoubleStart) {
-  // Daemon stopped in ctor, since no need to be running.
-  ExpectStopDaemon(false /* success */);
-  ArcDataSnapshotdManager manager(local_state(), base::DoNothing());
+  ArcDataSnapshotdManager manager(local_state());
   EXPECT_EQ(manager.state(), ArcDataSnapshotdManager::State::kNone);
   EXPECT_FALSE(manager.bridge());
 
@@ -224,11 +208,7 @@
 // Test that arc-data-snapshotd daemon is already stopped when |manager| tries
 // to stop it.
 TEST_F(ArcDataSnapshotdManagerBasicTest, UpstartFailures) {
-  // Daemon stopped in ctor, since no need to be running.
-  ExpectStopDaemon(false /* success */);
-
-  ArcDataSnapshotdManager manager(local_state(), base::DoNothing());
-
+  ArcDataSnapshotdManager manager(local_state());
   EXPECT_EQ(manager.state(), ArcDataSnapshotdManager::State::kNone);
   EXPECT_FALSE(manager.bridge());
 
@@ -245,11 +225,8 @@
   SetUpRestoredSessionCommandLine();
   // The attempt to stop the daemon, started before crash.
   ExpectStopDaemon(true /*success */);
-  ArcDataSnapshotdManager manager(local_state(), base::DoNothing());
+  ArcDataSnapshotdManager manager(local_state());
   EXPECT_EQ(manager.state(), ArcDataSnapshotdManager::State::kRestored);
-  EXPECT_FALSE(manager.IsAutoLoginConfigured());
-  EXPECT_TRUE(manager.IsAutoLoginAllowed());
-
   EXPECT_FALSE(manager.bridge());
 
   ExpectStartDaemon(true /*success */);
@@ -262,9 +239,8 @@
 // Test clear snapshots flow.
 TEST_P(ArcDataSnapshotdManagerFlowTest, ClearSnapshotsBasic) {
   // Set up two snapshots (previous and last) in local_state.
-  SetupLocalState(false /* blocked_ui_mode */);
-  CheckSnapshots(2 /* expected_snapshots_number */,
-                 false /* expected_blocked_ui_mode */);
+  SetupLocalState();
+  CheckSnapshotsNumber(2 /* expected_number */);
 
   // Once |manager| is created, it tries to clear both snapshots, because the
   // mechanism is disabled by default, and stop the daemon.
@@ -272,25 +248,21 @@
   ExpectStartDaemon(true /*success */);
   // Stop once finished clearing.
   ExpectStopDaemon(true /*success */);
-  ArcDataSnapshotdManager manager(local_state(), base::DoNothing());
+  ArcDataSnapshotdManager manager(local_state());
   RunUntilIdle();
 
   // No snapshots in local_state either.
   EXPECT_EQ(manager.state(), ArcDataSnapshotdManager::State::kNone);
-  EXPECT_FALSE(manager.IsAutoLoginConfigured());
-  EXPECT_TRUE(manager.IsAutoLoginAllowed());
-  CheckSnapshots(0 /* expected_snapshots_number */,
-                 false /* expected_blocked_ui_mode */);
+  CheckSnapshotsNumber(0 /* expected_number */);
 
   EXPECT_FALSE(manager.bridge());
-  TearDownLocalState();
 }
 
 // Test blocked UI mode flow.
 TEST_P(ArcDataSnapshotdManagerFlowTest, BlockedUiBasic) {
   // Set up two snapshots (previous and last) in local_state.
-  SetupLocalState(true /* blocked_ui_mode */);
-  CheckSnapshots(2 /* expected_snapshots_number */);
+  SetupLocalState();
+  CheckSnapshotsNumber(2 /* expected_number */);
   // Enable snapshotting mechanism for testing.
   ArcDataSnapshotdManager::set_snapshot_enabled_for_testing(true /* enabled */);
 
@@ -300,39 +272,21 @@
   ExpectStartDaemon(true /*success */);
   // Stop once finished clearing.
   ExpectStopDaemon(true /*success */);
-  bool is_attempt_user_exit_called = false;
-  ArcDataSnapshotdManager manager(
-      local_state(),
-      base::BindLambdaForTesting([&is_attempt_user_exit_called]() {
-        is_attempt_user_exit_called = true;
-      }));
+  ArcDataSnapshotdManager manager(local_state());
   CheckHeadlessMode();
   EXPECT_EQ(manager.state(), ArcDataSnapshotdManager::State::kBlockedUi);
-  EXPECT_TRUE(manager.IsAutoLoginConfigured());
-  EXPECT_FALSE(manager.IsAutoLoginAllowed());
-
   RunUntilIdle();
 
-  if (is_dbus_client_available()) {
-    EXPECT_FALSE(is_attempt_user_exit_called);
-    EXPECT_EQ(manager.state(), ArcDataSnapshotdManager::State::kMgsToLaunch);
-    EXPECT_TRUE(manager.IsAutoLoginConfigured());
-    EXPECT_TRUE(manager.IsAutoLoginAllowed());
+  // Snapshots are valid, no need to clear.
+  CheckSnapshotsNumber(2 /* expected_number */);
 
-    EXPECT_TRUE(manager.bridge());
-    // Starts a last snapshot creation. last became previous.
-    CheckSnapshots(1 /* expected_snapshots_number */,
-                   true /*expected_blocked_ui */,
-                   true /* expected_snapshot_started */);
-  } else {
-    EXPECT_TRUE(is_attempt_user_exit_called);
-    EXPECT_EQ(manager.state(), ArcDataSnapshotdManager::State::kBlockedUi);
-    EXPECT_FALSE(manager.bridge());
-    // Snapshots are valid. No need to clear.
-    CheckSnapshots(2 /* expected_snapshots_number */,
-                   false /* expected_blocked_ui */);
-  }
-  TearDownLocalState();
+  auto expected_state = is_dbus_client_available()
+                            ? ArcDataSnapshotdManager::State::kMgsToLaunch
+                            : ArcDataSnapshotdManager::State::kBlockedUi;
+
+  // The communication is established and MGS can be launched.
+  EXPECT_EQ(manager.state(), expected_state);
+  EXPECT_TRUE(manager.bridge());
 }
 
 INSTANTIATE_TEST_SUITE_P(ArcDataSnapshotdManagerFlowTest,
diff --git a/components/crash/content/browser/error_reporting/send_javascript_error_report.cc b/components/crash/content/browser/error_reporting/send_javascript_error_report.cc
index 1ce1aeb..7c31f25 100644
--- a/components/crash/content/browser/error_reporting/send_javascript_error_report.cc
+++ b/components/crash/content/browser/error_reporting/send_javascript_error_report.cc
@@ -267,8 +267,12 @@
   params["browser"] = "Chrome";
   params["browser_version"] = platform.version;
   params["channel"] = platform.channel;
-  // TODO(https://crbug.com/1121816): Handle non-ChromeOS platforms.
+#if defined(OS_CHROMEOS) || BUILDFLAG(IS_LACROS)
+  // base::SysInfo::OperatingSystemName() returns "Linux" on ChromeOS devices.
   params["os"] = "ChromeOS";
+#else
+  params["os"] = base::SysInfo::OperatingSystemName();
+#endif
   params["os_version"] = platform.os_version;
   params["full_url"] = source.spec();
   params["url"] = source.path();
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn
index 3c27ddd..2ff08f53 100644
--- a/components/exo/BUILD.gn
+++ b/components/exo/BUILD.gn
@@ -129,7 +129,6 @@
       "//chromeos/constants",
       "//chromeos/crosapi/cpp",
       "//chromeos/ui/base",
-      "//chromeos/ui/frame",
       "//ui/events/ozone/layout",
     ]
     sources += [
@@ -303,7 +302,6 @@
       "//ash/keyboard/ui",
       "//ash/public/cpp",
       "//chromeos/constants",
-      "//chromeos/ui/frame",
       "//ui/base:test_support",
       "//ui/base/cursor/mojom:cursor_type",
       "//ui/base/dragdrop/mojom:mojom_shared",
diff --git a/components/exo/DEPS b/components/exo/DEPS
index 9b0c1e4..46b7ed2d 100644
--- a/components/exo/DEPS
+++ b/components/exo/DEPS
@@ -5,7 +5,6 @@
   "+chromeos/constants/chromeos_features.h",
   "+chromeos/crosapi/cpp/crosapi_constants.h",
   "+chromeos/ui/base/window_state_type.h",
-  "+chromeos/ui/frame/caption_buttons",
   "+components/viz/common",
   "+components/viz/host",
   "+device/gamepad",
diff --git a/components/exo/client_controlled_shell_surface.cc b/components/exo/client_controlled_shell_surface.cc
index 5bbc164..467443f 100644
--- a/components/exo/client_controlled_shell_surface.cc
+++ b/components/exo/client_controlled_shell_surface.cc
@@ -11,6 +11,7 @@
 #include "ash/frame/non_client_frame_view_ash.h"
 #include "ash/frame/wide_frame_view.h"
 #include "ash/public/cpp/ash_features.h"
+#include "ash/public/cpp/caption_buttons/caption_button_model.h"
 #include "ash/public/cpp/default_frame_header.h"
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h"
 #include "ash/public/cpp/rounded_corner_decorator.h"
@@ -38,7 +39,6 @@
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/traced_value.h"
 #include "chromeos/ui/base/window_state_type.h"
-#include "chromeos/ui/frame/caption_buttons/caption_button_model.h"
 #include "components/exo/shell_surface_util.h"
 #include "components/exo/surface.h"
 #include "components/exo/wm_helper.h"
@@ -214,7 +214,7 @@
   return window_state->IsPinned() || window_state->IsTrustedPinned();
 }
 
-class CaptionButtonModel : public chromeos::CaptionButtonModel {
+class CaptionButtonModel : public ash::CaptionButtonModel {
  public:
   CaptionButtonModel(uint32_t visible_button_mask, uint32_t enabled_button_mask)
       : visible_button_mask_(visible_button_mask),
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc
index aafbbd3..1c0e2b7 100644
--- a/components/exo/client_controlled_shell_surface_unittest.cc
+++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -8,6 +8,8 @@
 #include "ash/frame/header_view.h"
 #include "ash/frame/non_client_frame_view_ash.h"
 #include "ash/frame/wide_frame_view.h"
+#include "ash/public/cpp/caption_buttons/caption_button_model.h"
+#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/public/cpp/test/shell_test_api.h"
 #include "ash/public/cpp/window_pin_type.h"
 #include "ash/public/cpp/window_properties.h"
@@ -31,8 +33,6 @@
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "cc/paint/display_item_list.h"
-#include "chromeos/ui/frame/caption_buttons/caption_button_model.h"
-#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "components/exo/buffer.h"
 #include "components/exo/display.h"
 #include "components/exo/pointer.h"
@@ -1503,7 +1503,7 @@
   ash::NonClientFrameViewAsh* frame_view =
       static_cast<ash::NonClientFrameViewAsh*>(
           shell_surface->GetWidget()->non_client_view()->frame_view());
-  chromeos::FrameCaptionButtonContainerView* container =
+  ash::FrameCaptionButtonContainerView* container =
       static_cast<ash::HeaderView*>(frame_view->GetHeaderView())
           ->caption_button_container();
 
@@ -1511,7 +1511,7 @@
   for (auto visible : kAllButtons) {
     uint32_t visible_buttons = 1 << visible;
     shell_surface->SetFrameButtons(visible_buttons, 0);
-    const chromeos::CaptionButtonModel* model = container->model();
+    const ash::CaptionButtonModel* model = container->model();
     for (auto not_visible : kAllButtons) {
       if (not_visible != visible)
         EXPECT_FALSE(model->IsVisible(not_visible));
@@ -1524,7 +1524,7 @@
   for (auto enabled : kAllButtons) {
     uint32_t enabled_buttons = 1 << enabled;
     shell_surface->SetFrameButtons(kAllButtonMask, enabled_buttons);
-    const chromeos::CaptionButtonModel* model = container->model();
+    const ash::CaptionButtonModel* model = container->model();
     for (auto not_enabled : kAllButtons) {
       if (not_enabled != enabled)
         EXPECT_FALSE(model->IsEnabled(not_enabled));
diff --git a/components/leveldb_proto/internal/leveldb_proto_feature_list.cc b/components/leveldb_proto/internal/leveldb_proto_feature_list.cc
index 5b302bac..a4b4825 100644
--- a/components/leveldb_proto/internal/leveldb_proto_feature_list.cc
+++ b/components/leveldb_proto/internal/leveldb_proto_feature_list.cc
@@ -7,6 +7,6 @@
 namespace leveldb_proto {
 
 const base::Feature kProtoDBSharedMigration{"ProtoDBSharedMigration",
-                                            base::FEATURE_DISABLED_BY_DEFAULT};
+                                            base::FEATURE_ENABLED_BY_DEFAULT};
 
 }  // namespace leveldb_proto
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
index 2ba72ce3..0068bb9 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
@@ -39,6 +39,49 @@
 
 namespace subresource_filter {
 
+namespace {
+
+bool ShouldInheritOpenerActivation(content::NavigationHandle* navigation_handle,
+                                   content::RenderFrameHost* frame_host) {
+  if (!navigation_handle->IsInMainFrame()) {
+    return false;
+  }
+
+  // If this navigation is for a special url that did not go through the network
+  // stack or if the initial (attempted) load wasn't committed, the frame's
+  // activation will not have been set. It should instead be inherited from its
+  // same-origin opener (if any). See ShouldInheritParentActivation() for
+  // subframes.
+  content::RenderFrameHost* opener_rfh =
+      navigation_handle->GetWebContents()->GetOpener();
+  if (!opener_rfh) {
+    return false;
+  }
+
+  if (!frame_host->GetLastCommittedOrigin().IsSameOriginWith(
+          opener_rfh->GetLastCommittedOrigin())) {
+    return false;
+  }
+
+  return ShouldInheritActivation(navigation_handle->GetURL()) ||
+         !navigation_handle->HasCommitted();
+}
+
+bool ShouldInheritParentActivation(
+    content::NavigationHandle* navigation_handle) {
+  if (navigation_handle->IsInMainFrame()) {
+    return false;
+  }
+  DCHECK(navigation_handle->GetParentFrame());
+
+  // As with ShouldInheritSameOriginOpenerActivation() except that we inherit
+  // from the parent frame as we are a subframe.
+  return ShouldInheritActivation(navigation_handle->GetURL()) ||
+         !navigation_handle->HasCommitted();
+}
+
+}  // namespace
+
 const char ContentSubresourceFilterThrottleManager::
     kContentSubresourceFilterThrottleManagerWebContentsUserDataKey[] =
         "content_subresource_filter_throttle_manager";
@@ -201,11 +244,12 @@
 
 void ContentSubresourceFilterThrottleManager::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
-  // Make sure not to leak throttle pointers.
   ActivationStateComputingNavigationThrottle* throttle = nullptr;
   auto throttle_it = ongoing_activation_throttles_.find(navigation_handle);
   if (throttle_it != ongoing_activation_throttles_.end()) {
     throttle = throttle_it->second;
+
+    // Make sure not to leak throttle pointers.
     ongoing_activation_throttles_.erase(throttle_it);
   }
 
@@ -213,40 +257,28 @@
   if (navigation_handle->IsSameDocument()) {
     return;
   }
-  if (!navigation_handle->HasCommitted()) {
-    // TODO(crbug.com/1055558): Handle the case of an aborted main frame load.
 
-    // If the initial load was aborted, the frame's activation will never have
-    // been set and should instead be inherited from its parents. Reuse the
-    // previous activation in the case of a non-initial aborted load.
-    if (!navigation_handle->IsInMainFrame() &&
-        navigation_handle->GetNetErrorCode() == net::ERR_ABORTED) {
-      // Cannot get the RFH from navigation_handle due to the aborted load.
-      content::RenderFrameHost* frame_host =
-          navigation_handle->GetWebContents()->UnsafeFindFrameByFrameTreeNodeId(
-              navigation_handle->GetFrameTreeNodeId());
-
-      // The RenderFrameHost will still exist as, even if a frame is destroyed,
-      // the NavigationHandle is destroyed (resulting in a call to
-      // DidFinishNavigation) before the RenderFrameHost is.
-      DCHECK(frame_host);
-      if (navigated_frames_.insert(frame_host).second) {
-        DCHECK(!base::Contains(frame_host_filter_map_, frame_host));
-        frame_host_filter_map_[frame_host] = nullptr;
-      }
-    }
+  // Cannot get the RFH from |navigation_handle| if there's no committed load.
+  content::RenderFrameHost* frame_host =
+      navigation_handle->HasCommitted()
+          ? navigation_handle->GetRenderFrameHost()
+          : navigation_handle->GetWebContents()
+                ->UnsafeFindFrameByFrameTreeNodeId(
+                    navigation_handle->GetFrameTreeNodeId());
+  if (!frame_host) {
+    DCHECK(!navigation_handle->HasCommitted());
     return;
   }
 
-  std::unique_ptr<AsyncDocumentSubresourceFilter> filter;
-  if (throttle) {
-    CHECK_EQ(navigation_handle, throttle->navigation_handle());
-    filter = throttle->ReleaseFilter();
+  // Reuse the previous activation if this attempted load was neither the
+  // initial load nor committed.
+  if (!navigated_frames_.insert(frame_host).second &&
+      !navigation_handle->HasCommitted()) {
+    return;
   }
 
-  content::RenderFrameHost* frame_host =
-      navigation_handle->GetRenderFrameHost();
-  navigated_frames_.insert(frame_host);
+  AsyncDocumentSubresourceFilter* filter =
+      FilterForFinishedNavigation(navigation_handle, throttle, frame_host);
 
   if (navigation_handle->IsInMainFrame()) {
     current_committed_load_has_notified_disallowed_load_ = false;
@@ -269,24 +301,77 @@
                               level);
   }
 
-  // Make sure |frame_host_filter_map_| is updated or cleaned up depending on
-  // this navigation's activation state.
-  if (filter) {
-    base::OnceClosure disallowed_callback(base::BindOnce(
-        &ContentSubresourceFilterThrottleManager::MaybeShowNotification,
-        weak_ptr_factory_.GetWeakPtr()));
-    filter->set_first_disallowed_load_callback(std::move(disallowed_callback));
-    frame_host_filter_map_[frame_host] = std::move(filter);
-  } else {
-    frame_host_filter_map_.erase(frame_host);
+  DestroyRulesetHandleIfNoLongerUsed();
+}
 
-    // If this is for a special url that did not go through the navigation
-    // throttles, then based on the parent's activation state, possibly add this
-    // to frame_host_filter_map_.
-    MaybeActivateSubframeSpecialUrls(navigation_handle);
+AsyncDocumentSubresourceFilter*
+ContentSubresourceFilterThrottleManager::FilterForFinishedNavigation(
+    content::NavigationHandle* navigation_handle,
+    ActivationStateComputingNavigationThrottle* throttle,
+    content::RenderFrameHost* frame_host) {
+  DCHECK(navigation_handle);
+  DCHECK(frame_host);
+
+  std::unique_ptr<AsyncDocumentSubresourceFilter> filter;
+
+  if (navigation_handle->HasCommitted() && throttle) {
+    CHECK_EQ(navigation_handle, throttle->navigation_handle());
+    filter = throttle->ReleaseFilter();
   }
 
-  DestroyRulesetHandleIfNoLongerUsed();
+  // If the frame should inherit its activation then, if it has an activated
+  // opener, construct a filter with the inherited activation state. The
+  // filter's activation state will be available immediately so a throttle is
+  // not required. Instead, we construct the filter synchronously.
+  if (ShouldInheritOpenerActivation(navigation_handle, frame_host)) {
+    content::RenderFrameHost* opener_rfh =
+        navigation_handle->GetWebContents()->GetOpener();
+    base::Optional<mojom::ActivationState> opener_activation;
+    if (auto* opener_throttle_manager =
+            ContentSubresourceFilterThrottleManager::FromWebContents(
+                content::WebContents::FromRenderFrameHost(opener_rfh))) {
+      opener_activation =
+          opener_throttle_manager->GetFrameActivationState(opener_rfh);
+    }
+
+    if (opener_activation && opener_activation->activation_level !=
+                                 mojom::ActivationLevel::kDisabled) {
+      DCHECK(dealer_handle_);
+
+      // This constructs the filter in a way that allows it to be immediately
+      // used. See the AsyncDocumentSubresourceFilter constructor for details.
+      filter = std::make_unique<AsyncDocumentSubresourceFilter>(
+          EnsureRulesetHandle(), frame_host->GetLastCommittedOrigin(),
+          *opener_activation);
+    }
+  }
+
+  // Make sure |frame_host_filter_map_| is updated or cleaned up depending on
+  // this navigation's activation state.
+  if (!filter) {
+    if (ShouldInheritParentActivation(navigation_handle) &&
+        base::Contains(frame_host_filter_map_,
+                       navigation_handle->GetParentFrame())) {
+      // TODO(crbug.com/1134288): Synchronously construct filters for subframes
+      // to inherit activation from their parents, instead of walking up the
+      // frame tree. Once done, consider updating the map in the caller.
+      // |nullptr| indicates a subframe inheriting its activation.
+      frame_host_filter_map_[frame_host] = nullptr;
+    } else {
+      frame_host_filter_map_.erase(frame_host);
+    }
+    return nullptr;
+  }
+
+  base::OnceClosure disallowed_callback(base::BindOnce(
+      &ContentSubresourceFilterThrottleManager::MaybeShowNotification,
+      weak_ptr_factory_.GetWeakPtr()));
+  filter->set_first_disallowed_load_callback(std::move(disallowed_callback));
+
+  AsyncDocumentSubresourceFilter* raw_ptr = filter.get();
+  frame_host_filter_map_[frame_host] = std::move(filter);
+
+  return raw_ptr;
 }
 
 void ContentSubresourceFilterThrottleManager::DidFinishLoad(
@@ -461,19 +546,33 @@
     content::NavigationHandle* child_frame_navigation) {
   DCHECK(!child_frame_navigation->IsInMainFrame());
   content::RenderFrameHost* parent = child_frame_navigation->GetParentFrame();
-  DCHECK(parent);
+  return GetFrameFilter(parent);
+}
+
+const base::Optional<subresource_filter::mojom::ActivationState>
+ContentSubresourceFilterThrottleManager::GetFrameActivationState(
+    content::RenderFrameHost* frame_host) {
+  if (AsyncDocumentSubresourceFilter* filter = GetFrameFilter(frame_host))
+    return filter->activation_state();
+  return base::nullopt;
+}
+
+AsyncDocumentSubresourceFilter*
+ContentSubresourceFilterThrottleManager::GetFrameFilter(
+    content::RenderFrameHost* frame_host) {
+  DCHECK(frame_host);
 
   // Filter will be null for those special url navigations that were added in
-  // MaybeActivateSubframeSpecialUrls and for subframes with no committed
-  // navigation. Return the filter of the first parent with a non-null filter.
-  while (parent) {
-    auto it = frame_host_filter_map_.find(parent);
+  // MaybeActivateSubframeSpecialUrls and for subframes with an aborted load.
+  // Return the filter of the first parent with a non-null filter.
+  while (frame_host) {
+    auto it = frame_host_filter_map_.find(frame_host);
     if (it == frame_host_filter_map_.end())
       return nullptr;
 
     if (it->second)
       return it->second.get();
-    parent = it->first->GetParent();
+    frame_host = it->first->GetParent();
   }
 
   // Since a null filter is only possible for special navigations of iframes and
@@ -548,23 +647,4 @@
     statistics_->OnDocumentLoadStatistics(*statistics);
 }
 
-void ContentSubresourceFilterThrottleManager::MaybeActivateSubframeSpecialUrls(
-    content::NavigationHandle* navigation_handle) {
-  if (navigation_handle->IsInMainFrame())
-    return;
-
-  if (!ShouldUseParentActivation(navigation_handle->GetURL()))
-    return;
-
-  content::RenderFrameHost* frame_host =
-      navigation_handle->GetRenderFrameHost();
-  if (!frame_host)
-    return;
-
-  content::RenderFrameHost* parent = navigation_handle->GetParentFrame();
-  DCHECK(parent);
-  if (base::Contains(frame_host_filter_map_, parent))
-    frame_host_filter_map_[frame_host] = nullptr;
-}
-
 }  // namespace subresource_filter
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
index 70df03b9..18109fa 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
+++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
@@ -189,6 +189,16 @@
   AsyncDocumentSubresourceFilter* GetParentFrameFilter(
       content::NavigationHandle* child_frame_navigation);
 
+  // Returns nullptr if the frame is not activated (and therefore has no
+  // subresource filter).
+  AsyncDocumentSubresourceFilter* GetFrameFilter(
+      content::RenderFrameHost* frame_host);
+
+  // Returns the activation state of the frame's filter. If the frame is not
+  // activated (and therefore has no subresource filter), returns base::nullopt.
+  const base::Optional<subresource_filter::mojom::ActivationState>
+  GetFrameActivationState(content::RenderFrameHost* frame_host);
+
   // Calls ShowNotification on |client_| at most once per committed,
   // non-same-page navigation in the main frame.
   void MaybeShowNotification();
@@ -206,12 +216,14 @@
   void SetDocumentLoadStatistics(
       mojom::DocumentLoadStatisticsPtr statistics) override;
 
-  // Adds the navigation's RenderFrameHost to activated_frame_hosts_ if it is a
-  // special navigation which did not go through navigation throttles and its
-  // parent frame is activated as well. The filter for these frames is set
-  // to nullptr.
-  void MaybeActivateSubframeSpecialUrls(
-      content::NavigationHandle* navigation_handle);
+  // Gets a filter for the navigation from |throttle|, creates and returns a new
+  // filter, or returns |nullptr|. Also updates |frame_host_filter_map_| as
+  // appropriate. |frame_host| is provided as |navigation_handle|'s getter
+  // cannot be used when the navigation has not committed.
+  AsyncDocumentSubresourceFilter* FilterForFinishedNavigation(
+      content::NavigationHandle* navigation_handle,
+      ActivationStateComputingNavigationThrottle* throttle,
+      content::RenderFrameHost* frame_host);
 
   // For each RenderFrameHost where the last committed load has subresource
   // filtering activated, owns the corresponding AsyncDocumentSubresourceFilter.
@@ -224,12 +236,13 @@
       frame_host_filter_map_;
 
   // Set of RenderFrameHosts that have had at least one committed or aborted
-  // navigation. Main frames with only aborted navigations are not included.
+  // navigation.
   std::set<content::RenderFrameHost*> navigated_frames_;
 
   // For each ongoing navigation that requires activation state computation,
   // keeps track of the throttle that is carrying out that computation, so that
   // the result can be retrieved when the navigation is ready to commit.
+  // TODO(crbug.com/1134311): Key with navigation IDs instead of raw pointers.
   std::map<content::NavigationHandle*,
            ActivationStateComputingNavigationThrottle*>
       ongoing_activation_throttles_;
diff --git a/components/subresource_filter/content/common/subresource_filter_utils.cc b/components/subresource_filter/content/common/subresource_filter_utils.cc
index ae1cb5d..9966138 100644
--- a/components/subresource_filter/content/common/subresource_filter_utils.cc
+++ b/components/subresource_filter/content/common/subresource_filter_utils.cc
@@ -8,7 +8,7 @@
 
 namespace subresource_filter {
 
-bool ShouldUseParentActivation(const GURL& url) {
+bool ShouldInheritActivation(const GURL& url) {
   return !content::IsURLHandledByNetworkStack(url);
 }
 
diff --git a/components/subresource_filter/content/common/subresource_filter_utils.h b/components/subresource_filter/content/common/subresource_filter_utils.h
index 460e16a..93e197e 100644
--- a/components/subresource_filter/content/common/subresource_filter_utils.h
+++ b/components/subresource_filter/content/common/subresource_filter_utils.h
@@ -9,10 +9,14 @@
 
 namespace subresource_filter {
 
-// Subframe navigations matching these URLs/schemes will not trigger
-// ReadyToCommitNavigation in the browser process, so they must be treated
-// specially to maintain activation. Should only be invoked for subframes.
-bool ShouldUseParentActivation(const GURL& url);
+// Subframe navigations and initial mainframe navigations matching these URLs/
+// schemes will not trigger ReadyToCommitNavigation in the browser process, so
+// they must be treated specially to maintain activation. Each should inherit
+// the activation of its parent in the case of a subframe and its opener in the
+// case of a mainframe. This also accounts for the ability of the parent/opener
+// to affect the frame's content more directly, e.g. through document.write(),
+// even though these URLs won't match a filter list rule by themselves.
+bool ShouldInheritActivation(const GURL& url);
 
 }  // namespace subresource_filter
 
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent.cc b/components/subresource_filter/content/renderer/subresource_filter_agent.cc
index 37fc27a1..90cb56c5 100644
--- a/components/subresource_filter/content/renderer/subresource_filter_agent.cc
+++ b/components/subresource_filter/content/renderer/subresource_filter_agent.cc
@@ -46,6 +46,18 @@
   DCHECK(ruleset_dealer);
   // |render_frame| can be nullptr in unit tests.
   if (render_frame) {
+    // If a mainframe has an activated opener, we activate the initial empty
+    // document, which is created before this constructor. This ensures that a
+    // popup's final document is appropriately activated, even when the the
+    // initial navigation is aborted and there are no further documents created.
+    if (render_frame->IsMainFrame() &&
+        GetInheritedActivationState(render_frame).activation_level !=
+            mojom::ActivationLevel::kDisabled) {
+      const GURL& url = GetDocumentURL();
+      DCHECK(url.is_empty());
+      DCHECK(ShouldInheritActivation(url));
+      ConstructFilter(GetInheritedActivationState(render_frame), url);
+    }
     render_frame->GetAssociatedInterfaceRegistry()->AddInterface(
         base::BindRepeating(
             &SubresourceFilterAgent::OnSubresourceFilterAgentRequest,
@@ -101,16 +113,34 @@
   render_frame()->GetWebFrame()->SetIsAdSubframe(ad_frame_type);
 }
 
-mojom::ActivationState SubresourceFilterAgent::GetParentActivationState(
+mojom::ActivationState SubresourceFilterAgent::GetInheritedActivationState(
     content::RenderFrame* render_frame) {
-  blink::WebFrame* parent =
-      render_frame ? render_frame->GetWebFrame()->Parent() : nullptr;
-  if (parent && parent->IsWebLocalFrame()) {
-    auto* agent = SubresourceFilterAgent::Get(
-        content::RenderFrame::FromWebFrame(parent->ToWebLocalFrame()));
+  DCHECK(ShouldInheritActivation(GetDocumentURL()));
+  if (!render_frame)
+    return mojom::ActivationState();
+
+  blink::WebFrame* frame_to_inherit_from =
+      render_frame->IsMainFrame() ? render_frame->GetWebFrame()->Opener()
+                                  : render_frame->GetWebFrame()->Parent();
+
+  if (!frame_to_inherit_from || !frame_to_inherit_from->IsWebLocalFrame())
+    return mojom::ActivationState();
+
+  // TODO(crbug.com/1134740): Add an IsSameOriginWith() function to
+  // WebSecurityOrigin to avoid unnecessary conversions to url::Origin.
+  url::Origin render_frame_origin =
+      render_frame->GetWebFrame()->GetSecurityOrigin();
+  url::Origin inherited_origin = frame_to_inherit_from->GetSecurityOrigin();
+
+  // Only inherit from same-origin frames.
+  if (render_frame_origin.IsSameOriginWith(inherited_origin)) {
+    auto* agent =
+        SubresourceFilterAgent::Get(content::RenderFrame::FromWebFrame(
+            frame_to_inherit_from->ToWebLocalFrame()));
     if (agent && agent->filter_for_last_created_document_)
       return agent->filter_for_last_created_document_->activation_state();
   }
+
   return mojom::ActivationState();
 }
 
@@ -173,8 +203,7 @@
   const bool should_record_histograms =
       !first_document_ &&
       !(IsMainFrame() && !url.SchemeIsHTTPOrHTTPS() && !url.SchemeIsFile());
-  if (first_document_) {
-    first_document_ = false;
+  if (first_document_ && !IsMainFrame()) {
     DCHECK(!filter_for_last_created_document_);
 
     // Local subframes will first create an initial empty document (with url
@@ -191,16 +220,11 @@
         SendFrameIsAdSubframe();
     }
   }
-
-  // Filter may outlive us, so reset the ad tracker.
-  if (filter_for_last_created_document_)
-    filter_for_last_created_document_->set_ad_resource_tracker(nullptr);
-  filter_for_last_created_document_.reset();
+  first_document_ = false;
 
   const mojom::ActivationState activation_state =
-      (!IsMainFrame() && ShouldUseParentActivation(url))
-          ? GetParentActivationState(render_frame())
-          : activation_state_for_next_document_;
+      ShouldInheritActivation(url) ? GetInheritedActivationState(render_frame())
+                                   : activation_state_for_next_document_;
 
   ResetInfoForNextDocument();
 
@@ -208,6 +232,17 @@
     RecordHistogramsOnFilterCreation(activation_state);
   }
 
+  ConstructFilter(activation_state, url);
+}
+
+void SubresourceFilterAgent::ConstructFilter(
+    const mojom::ActivationState activation_state,
+    const GURL& url) {
+  // Filter may outlive us, so reset the ad tracker.
+  if (filter_for_last_created_document_)
+    filter_for_last_created_document_->set_ad_resource_tracker(nullptr);
+  filter_for_last_created_document_.reset();
+
   if (activation_state.activation_level == mojom::ActivationLevel::kDisabled ||
       !ruleset_dealer_->IsRulesetFileAvailable())
     return;
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent.h b/components/subresource_filter/content/renderer/subresource_filter_agent.h
index f102434..e80a65ad 100644
--- a/components/subresource_filter/content/renderer/subresource_filter_agent.h
+++ b/components/subresource_filter/content/renderer/subresource_filter_agent.h
@@ -88,15 +88,22 @@
       blink::mojom::AdFrameType ad_frame_type) override;
 
  private:
-  // Assumes that the parent will be in a local frame relative to this one, upon
-  // construction.
-  virtual mojom::ActivationState GetParentActivationState(
+  // Returns the activation state for the |render_frame| to inherit. Main frames
+  // inherit from their opener frames, and subframes inherit from their parent
+  // frames. Assumes that the parent/opener is in a local frame relative to this
+  // one, upon construction. This function is virtual (and not static) to ease
+  // testing.
+  // TODO(crbug.com/1134747): Modify the test harness to allow this to be static
+  virtual mojom::ActivationState GetInheritedActivationState(
       content::RenderFrame* render_frame);
 
   void RecordHistogramsOnFilterCreation(
       const mojom::ActivationState& activation_state);
   void ResetInfoForNextDocument();
 
+  void ConstructFilter(const mojom::ActivationState activation_state,
+                       const GURL& url);
+
   mojom::SubresourceFilterHost* GetSubresourceFilterHost();
 
   void OnSubresourceFilterAgentRequest(
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc b/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc
index 8937149..afd594b 100644
--- a/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc
+++ b/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc
@@ -82,10 +82,10 @@
     return std::move(last_injected_filter_);
   }
 
-  void SetParentActivationState(mojom::ActivationLevel level) {
+  void SetInheritedActivationState(mojom::ActivationLevel level) {
     mojom::ActivationState state;
     state.activation_level = level;
-    parent_activation_state_ = state;
+    inherited_activation_state_ = state;
   }
 
   void SimulateNonInitialLoad() { SetFirstDocument(false); }
@@ -93,15 +93,15 @@
   using SubresourceFilterAgent::ActivateForNextCommittedLoad;
 
  private:
-  mojom::ActivationState GetParentActivationState(
+  mojom::ActivationState GetInheritedActivationState(
       content::RenderFrame*) override {
-    return parent_activation_state_;
+    return inherited_activation_state_;
   }
 
   std::unique_ptr<blink::WebDocumentSubresourceFilter> last_injected_filter_;
   bool is_ad_subframe_ = false;
   bool is_main_frame_ = true;
-  mojom::ActivationState parent_activation_state_;
+  mojom::ActivationState inherited_activation_state_;
 
   DISALLOW_COPY_AND_ASSIGN(SubresourceFilterAgentUnderTest);
 };
@@ -568,9 +568,25 @@
       SetTestRulesetToDisallowURLsWithPathSuffix("somethingNotMatched"));
 
   agent()->SetIsMainFrame(false);
-  agent()->SetParentActivationState(mojom::ActivationLevel::kEnabled);
+  agent()->SetInheritedActivationState(mojom::ActivationLevel::kEnabled);
 
-  // ExpectSubresourceFilterGetsInjected();
+  EXPECT_CALL(*agent(), GetDocumentURL())
+      .WillOnce(::testing::Return(GURL("about:blank")));
+  EXPECT_CALL(*agent(), OnSetSubresourceFilterForCurrentDocumentCalled());
+  StartLoadAndSetActivationState(mojom::ActivationLevel::kEnabled);
+
+  ExpectNoSubresourceFilterGetsInjected();
+  agent_as_rfo()->DidFailProvisionalLoad();
+}
+
+TEST_F(SubresourceFilterAgentTest,
+       FailedInitialMainFrameLoad_FilterInjectedOnInitialDocumentCreation) {
+  ASSERT_NO_FATAL_FAILURE(
+      SetTestRulesetToDisallowURLsWithPathSuffix("somethingNotMatched"));
+
+  agent()->SetIsMainFrame(true);
+  agent()->SetInheritedActivationState(mojom::ActivationLevel::kEnabled);
+
   EXPECT_CALL(*agent(), GetDocumentURL())
       .WillOnce(::testing::Return(GURL("about:blank")));
   EXPECT_CALL(*agent(), OnSetSubresourceFilterForCurrentDocumentCalled());
@@ -614,6 +630,7 @@
 
 TEST_F(SubresourceFilterAgentTest, DryRun_SendsFrameIsAdSubframe) {
   agent()->SetIsAdSubframe();
+  agent()->SetIsMainFrame(false);
   ExpectSendFrameIsAdSubframe();
 
   // Call DidCreateNewDocument twice and verify that SendFrameIsAdSubframe is
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn
index d09a73d3..aaf595f2 100644
--- a/components/sync/BUILD.gn
+++ b/components/sync/BUILD.gn
@@ -102,6 +102,8 @@
     "engine_impl/commit.cc",
     "engine_impl/commit.h",
     "engine_impl/commit_contribution.h",
+    "engine_impl/commit_contribution_impl.cc",
+    "engine_impl/commit_contribution_impl.h",
     "engine_impl/commit_contributor.h",
     "engine_impl/commit_processor.cc",
     "engine_impl/commit_processor.h",
@@ -112,8 +114,6 @@
     "engine_impl/cycle/data_type_tracker.cc",
     "engine_impl/cycle/data_type_tracker.h",
     "engine_impl/cycle/debug_info_getter.h",
-    "engine_impl/cycle/non_blocking_type_debug_info_emitter.cc",
-    "engine_impl/cycle/non_blocking_type_debug_info_emitter.h",
     "engine_impl/cycle/nudge_tracker.cc",
     "engine_impl/cycle/nudge_tracker.h",
     "engine_impl/cycle/status_controller.cc",
@@ -172,8 +172,6 @@
     "engine_impl/net/sync_server_connection_manager.h",
     "engine_impl/net/url_translator.cc",
     "engine_impl/net/url_translator.h",
-    "engine_impl/non_blocking_type_commit_contribution.cc",
-    "engine_impl/non_blocking_type_commit_contribution.h",
     "engine_impl/nudge_handler.h",
     "engine_impl/nudge_source.h",
     "engine_impl/sync_cycle_event.cc",
@@ -449,6 +447,7 @@
     "engine/sync_backend_registrar_unittest.cc",
     "engine_impl/backoff_delay_provider_unittest.cc",
     "engine_impl/bookmark_update_preprocessing_unittest.cc",
+    "engine_impl/commit_contribution_impl_unittest.cc",
     "engine_impl/commit_processor_unittest.cc",
     "engine_impl/cycle/data_type_debug_info_emitter_unittest.cc",
     "engine_impl/cycle/nudge_tracker_unittest.cc",
@@ -466,7 +465,6 @@
     "engine_impl/model_type_registry_unittest.cc",
     "engine_impl/model_type_worker_unittest.cc",
     "engine_impl/net/sync_server_connection_manager_unittest.cc",
-    "engine_impl/non_blocking_type_commit_contribution_unittest.cc",
     "engine_impl/sync_manager_impl_unittest.cc",
     "engine_impl/sync_scheduler_impl_unittest.cc",
     "engine_impl/syncer_proto_util_unittest.cc",
diff --git a/components/sync/engine_impl/non_blocking_type_commit_contribution.cc b/components/sync/engine_impl/commit_contribution_impl.cc
similarity index 94%
rename from components/sync/engine_impl/non_blocking_type_commit_contribution.cc
rename to components/sync/engine_impl/commit_contribution_impl.cc
index 07d6cbe..4889948 100644
--- a/components/sync/engine_impl/non_blocking_type_commit_contribution.cc
+++ b/components/sync/engine_impl/commit_contribution_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/sync/engine_impl/non_blocking_type_commit_contribution.h"
+#include "components/sync/engine_impl/commit_contribution_impl.h"
 
 #include <algorithm>
 #include <utility>
@@ -17,7 +17,7 @@
 
 namespace syncer {
 
-NonBlockingTypeCommitContribution::NonBlockingTypeCommitContribution(
+CommitContributionImpl::CommitContributionImpl(
     ModelType type,
     const sync_pb::DataTypeContext& context,
     CommitRequestDataList commit_requests,
@@ -41,11 +41,11 @@
       debug_info_emitter_(debug_info_emitter),
       only_commit_specifics_(only_commit_specifics) {}
 
-NonBlockingTypeCommitContribution::~NonBlockingTypeCommitContribution() {
+CommitContributionImpl::~CommitContributionImpl() {
   DCHECK(cleaned_up_);
 }
 
-void NonBlockingTypeCommitContribution::AddToCommitMessage(
+void CommitContributionImpl::AddToCommitMessage(
     sync_pb::ClientToServerMessage* msg) {
   sync_pb::CommitMessage* commit_message = msg->mutable_commit();
   entries_start_index_ = commit_message->entries_size();
@@ -86,7 +86,7 @@
     commit_message->add_client_contexts()->CopyFrom(context_);
 }
 
-SyncerError NonBlockingTypeCommitContribution::ProcessCommitResponse(
+SyncerError CommitContributionImpl::ProcessCommitResponse(
     const sync_pb::ClientToServerResponse& response,
     StatusController* status) {
   const sync_pb::CommitResponse& commit_response = response.commit();
@@ -188,24 +188,24 @@
   }
 }
 
-void NonBlockingTypeCommitContribution::ProcessCommitFailure(
+void CommitContributionImpl::ProcessCommitFailure(
     SyncCommitError commit_error) {
   std::move(on_full_commit_failure_callback_).Run(commit_error);
   on_commit_response_callback_.Reset();
 }
 
-void NonBlockingTypeCommitContribution::CleanUp() {
+void CommitContributionImpl::CleanUp() {
   cleaned_up_ = true;
 
   debug_info_emitter_->EmitCommitCountersUpdate();
 }
 
-size_t NonBlockingTypeCommitContribution::GetNumEntries() const {
+size_t CommitContributionImpl::GetNumEntries() const {
   return commit_requests_.size();
 }
 
 // static
-void NonBlockingTypeCommitContribution::PopulateCommitProto(
+void CommitContributionImpl::PopulateCommitProto(
     ModelType type,
     const CommitRequestData& commit_entity,
     sync_pb::SyncEntity* commit_proto) {
@@ -246,7 +246,7 @@
   }
 }
 
-void NonBlockingTypeCommitContribution::AdjustCommitProto(
+void CommitContributionImpl::AdjustCommitProto(
     sync_pb::SyncEntity* commit_proto) {
   if (commit_proto->version() == kUncommittedVersion) {
     commit_proto->set_version(0);
diff --git a/components/sync/engine_impl/non_blocking_type_commit_contribution.h b/components/sync/engine_impl/commit_contribution_impl.h
similarity index 87%
rename from components/sync/engine_impl/non_blocking_type_commit_contribution.h
rename to components/sync/engine_impl/commit_contribution_impl.h
index 46697df..f7535300 100644
--- a/components/sync/engine_impl/non_blocking_type_commit_contribution.h
+++ b/components/sync/engine_impl/commit_contribution_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_SYNC_ENGINE_IMPL_NON_BLOCKING_TYPE_COMMIT_CONTRIBUTION_H_
-#define COMPONENTS_SYNC_ENGINE_IMPL_NON_BLOCKING_TYPE_COMMIT_CONTRIBUTION_H_
+#ifndef COMPONENTS_SYNC_ENGINE_IMPL_COMMIT_CONTRIBUTION_IMPL_H_
+#define COMPONENTS_SYNC_ENGINE_IMPL_COMMIT_CONTRIBUTION_IMPL_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -22,17 +22,17 @@
 class Cryptographer;
 class ModelTypeWorker;
 
-// A non-blocking sync type's contribution to an outgoing commit message.
+// A sync type's contribution to an outgoing commit message.
 //
 // Helps build a commit message and process its response.  It collaborates
 // closely with the ModelTypeWorker.
-class NonBlockingTypeCommitContribution : public CommitContribution {
+class CommitContributionImpl : public CommitContribution {
  public:
   // Note: only one of |on_commit_response_callback| and
   // |on_full_commit_failure_callback| will be called.
   // TODO(rushans): there is still possible rare case when both of these
   // callbacks are never called, i.e. if get updates from the server fails.
-  NonBlockingTypeCommitContribution(
+  CommitContributionImpl(
       ModelType type,
       const sync_pb::DataTypeContext& context,
       CommitRequestDataList commit_requests,
@@ -44,7 +44,7 @@
       PassphraseType passphrase_type,
       DataTypeDebugInfoEmitter* debug_info_emitter,
       bool only_commit_specifics);
-  ~NonBlockingTypeCommitContribution() override;
+  ~CommitContributionImpl() override;
 
   // Implementation of CommitContribution
   void AddToCommitMessage(sync_pb::ClientToServerMessage* msg) override;
@@ -104,9 +104,9 @@
   // commit only types to save bandwidth.
   bool only_commit_specifics_;
 
-  DISALLOW_COPY_AND_ASSIGN(NonBlockingTypeCommitContribution);
+  DISALLOW_COPY_AND_ASSIGN(CommitContributionImpl);
 };
 
 }  // namespace syncer
 
-#endif  // COMPONENTS_SYNC_ENGINE_IMPL_NON_BLOCKING_TYPE_COMMIT_CONTRIBUTION_H_
+#endif  // COMPONENTS_SYNC_ENGINE_IMPL_COMMIT_CONTRIBUTION_IMPL_H_
diff --git a/components/sync/engine_impl/non_blocking_type_commit_contribution_unittest.cc b/components/sync/engine_impl/commit_contribution_impl_unittest.cc
similarity index 92%
rename from components/sync/engine_impl/non_blocking_type_commit_contribution_unittest.cc
rename to components/sync/engine_impl/commit_contribution_impl_unittest.cc
index 6e2716bb..9c5a10a 100644
--- a/components/sync/engine_impl/non_blocking_type_commit_contribution_unittest.cc
+++ b/components/sync/engine_impl/commit_contribution_impl_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/sync/engine_impl/non_blocking_type_commit_contribution.h"
+#include "components/sync/engine_impl/commit_contribution_impl.h"
 
 #include <memory>
 #include <string>
@@ -48,7 +48,7 @@
   return specifics;
 }
 
-TEST(NonBlockingTypeCommitContributionTest, PopulateCommitProtoDefault) {
+TEST(CommitContributionImplTest, PopulateCommitProtoDefault) {
   const int64_t kBaseVersion = 7;
   base::Time creation_time =
       base::Time::UnixEpoch() + base::TimeDelta::FromDays(1);
@@ -74,8 +74,8 @@
   request_data.entity = std::move(data);
 
   SyncEntity entity;
-  NonBlockingTypeCommitContribution::PopulateCommitProto(PREFERENCES,
-                                                         request_data, &entity);
+  CommitContributionImpl::PopulateCommitProto(PREFERENCES, request_data,
+                                              &entity);
 
   // Exhaustively verify the populated SyncEntity.
   EXPECT_TRUE(entity.id_string().empty());
@@ -92,7 +92,7 @@
   EXPECT_EQ(0, entity.position_in_parent());
 }
 
-TEST(NonBlockingTypeCommitContributionTest, PopulateCommitProtoBookmark) {
+TEST(CommitContributionImplTest, PopulateCommitProtoBookmark) {
   const int64_t kBaseVersion = 7;
   base::Time creation_time =
       base::Time::UnixEpoch() + base::TimeDelta::FromDays(1);
@@ -123,8 +123,7 @@
   request_data.entity = std::move(data);
 
   SyncEntity entity;
-  NonBlockingTypeCommitContribution::PopulateCommitProto(BOOKMARKS,
-                                                         request_data, &entity);
+  CommitContributionImpl::PopulateCommitProto(BOOKMARKS, request_data, &entity);
 
   // Exhaustively verify the populated SyncEntity.
   EXPECT_FALSE(entity.id_string().empty());
@@ -144,7 +143,7 @@
 
 // Verifies how PASSWORDS protos are committed on the wire, making sure the data
 // is properly encrypted except for password metadata.
-TEST(NonBlockingTypeCommitContributionTest,
+TEST(CommitContributionImplTest,
      PopulateCommitProtoPasswordWithoutCustomPassphrase) {
   const std::string kMetadataUrl = "http://foo.com";
   const std::string kSignonRealm = "signon_realm";
@@ -173,7 +172,7 @@
 
   CommitRequestDataList requests_data;
   requests_data.push_back(std::move(request_data));
-  NonBlockingTypeCommitContribution contribution(
+  CommitContributionImpl contribution(
       PASSWORDS, sync_pb::DataTypeContext(), std::move(requests_data),
       /*on_commit_response_callback=*/base::NullCallback(),
       /*on_full_commit_failure_callback=*/base::NullCallback(),
@@ -210,7 +209,7 @@
 
 // Same as above but uses CUSTOM_PASSPHRASE. In this case, field
 // |unencrypted_metadata| should be cleared.
-TEST(NonBlockingTypeCommitContributionTest,
+TEST(CommitContributionImplTest,
      PopulateCommitProtoPasswordWithCustomPassphrase) {
   const std::string kMetadataUrl = "http://foo.com";
   const std::string kSignonRealm = "signon_realm";
@@ -239,7 +238,7 @@
 
   CommitRequestDataList requests_data;
   requests_data.push_back(std::move(request_data));
-  NonBlockingTypeCommitContribution contribution(
+  CommitContributionImpl contribution(
       PASSWORDS, sync_pb::DataTypeContext(), std::move(requests_data),
       /*on_commit_response_callback=*/base::NullCallback(),
       /*on_full_commit_failure_callback=*/base::NullCallback(),
@@ -269,8 +268,7 @@
   EXPECT_EQ(0, entity.position_in_parent());
 }
 
-TEST(NonBlockingTypeCommitContributionTest,
-     ShouldPropagateFailedItemsOnCommitResponse) {
+TEST(CommitContributionImplTest, ShouldPropagateFailedItemsOnCommitResponse) {
   auto data = std::make_unique<syncer::EntityData>();
   data->client_tag_hash = ClientTagHash::FromHashed("hash");
   auto request_data = std::make_unique<CommitRequestData>();
@@ -295,7 +293,7 @@
       },
       &actual_error_response_list);
 
-  NonBlockingTypeCommitContribution contribution(
+  CommitContributionImpl contribution(
       PASSWORDS, sync_pb::DataTypeContext(), std::move(requests_data),
       std::move(on_commit_response_callback),
       /*on_full_commit_failure_callback=*/base::NullCallback(),
@@ -333,14 +331,14 @@
       failed_item.datatype_specific_error.sharing_message_error().error_code());
 }
 
-TEST(NonBlockingTypeCommitContributionTest, ShouldPropagateFullCommitFailure) {
+TEST(CommitContributionImplTest, ShouldPropagateFullCommitFailure) {
   DataTypeDebugInfoEmitter debug_info_emitter(BOOKMARKS);
 
   base::MockOnceCallback<void(SyncCommitError commit_error)>
       on_commit_failure_callback;
   EXPECT_CALL(on_commit_failure_callback, Run(SyncCommitError::kNetworkError));
 
-  NonBlockingTypeCommitContribution contribution(
+  CommitContributionImpl contribution(
       BOOKMARKS, sync_pb::DataTypeContext(), CommitRequestDataList(),
       /*on_commit_response_callback=*/base::NullCallback(),
       on_commit_failure_callback.Get(), /*cryptographer=*/nullptr,
diff --git a/components/sync/engine_impl/cycle/data_type_debug_info_emitter.cc b/components/sync/engine_impl/cycle/data_type_debug_info_emitter.cc
index 28f7d70..7bd8005 100644
--- a/components/sync/engine_impl/cycle/data_type_debug_info_emitter.cc
+++ b/components/sync/engine_impl/cycle/data_type_debug_info_emitter.cc
@@ -55,7 +55,7 @@
 }  // namespace
 
 DataTypeDebugInfoEmitter::DataTypeDebugInfoEmitter(ModelType type)
-    : type_(type), histogram_(GetModelTypeEntityChangeHistogram(type)) {
+    : histogram_(GetModelTypeEntityChangeHistogram(type)) {
   DCHECK(histogram_);
 }
 
diff --git a/components/sync/engine_impl/cycle/data_type_debug_info_emitter.h b/components/sync/engine_impl/cycle/data_type_debug_info_emitter.h
index d48a2f8..06f414a 100644
--- a/components/sync/engine_impl/cycle/data_type_debug_info_emitter.h
+++ b/components/sync/engine_impl/cycle/data_type_debug_info_emitter.h
@@ -20,7 +20,6 @@
 
 // Supports various kinds of debugging requests for a certain directory type.
 //
-// TODO(crbug.com/1102849): Merge with NonBlockingDataTypeDebugInfoEmitter.
 // TODO(crbug.com/1102849): Rename Emit*() methods to mention UMA, and update
 // the documentation to not mention any observers.
 // The Emit*() functions send updates to registered TypeDebugInfoObservers.
@@ -55,9 +54,6 @@
   // Triggers an update counters update to registered observers.
   void EmitUpdateCountersUpdate();
 
- protected:
-  const ModelType type_;
-
  private:
   // The actual up-to-date counters.
   CommitCounters commit_counters_;
diff --git a/components/sync/engine_impl/cycle/non_blocking_type_debug_info_emitter.cc b/components/sync/engine_impl/cycle/non_blocking_type_debug_info_emitter.cc
deleted file mode 100644
index 53d27e1..0000000
--- a/components/sync/engine_impl/cycle/non_blocking_type_debug_info_emitter.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2016 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/sync/engine_impl/cycle/non_blocking_type_debug_info_emitter.h"
-
-namespace syncer {
-
-NonBlockingTypeDebugInfoEmitter::NonBlockingTypeDebugInfoEmitter(ModelType type)
-    : DataTypeDebugInfoEmitter(type) {}
-
-NonBlockingTypeDebugInfoEmitter::~NonBlockingTypeDebugInfoEmitter() {}
-
-}  // namespace syncer
diff --git a/components/sync/engine_impl/cycle/non_blocking_type_debug_info_emitter.h b/components/sync/engine_impl/cycle/non_blocking_type_debug_info_emitter.h
deleted file mode 100644
index 1deebc7..0000000
--- a/components/sync/engine_impl/cycle/non_blocking_type_debug_info_emitter.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2016 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_SYNC_ENGINE_IMPL_CYCLE_NON_BLOCKING_TYPE_DEBUG_INFO_EMITTER_H_
-#define COMPONENTS_SYNC_ENGINE_IMPL_CYCLE_NON_BLOCKING_TYPE_DEBUG_INFO_EMITTER_H_
-
-#include "base/macros.h"
-#include "components/sync/engine_impl/cycle/data_type_debug_info_emitter.h"
-
-namespace syncer {
-
-class NonBlockingTypeDebugInfoEmitter : public DataTypeDebugInfoEmitter {
- public:
-  explicit NonBlockingTypeDebugInfoEmitter(ModelType type);
-
-  ~NonBlockingTypeDebugInfoEmitter() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NonBlockingTypeDebugInfoEmitter);
-};
-
-}  // namespace syncer
-
-#endif  // COMPONENTS_SYNC_ENGINE_IMPL_CYCLE_NON_BLOCKING_TYPE_DEBUG_INFO_EMITTER_H_
diff --git a/components/sync/engine_impl/model_type_registry.cc b/components/sync/engine_impl/model_type_registry.cc
index aed453a6..09856c5 100644
--- a/components/sync/engine_impl/model_type_registry.cc
+++ b/components/sync/engine_impl/model_type_registry.cc
@@ -15,7 +15,7 @@
 #include "components/sync/engine/commit_queue.h"
 #include "components/sync/engine/data_type_activation_response.h"
 #include "components/sync/engine/model_type_processor.h"
-#include "components/sync/engine_impl/cycle/non_blocking_type_debug_info_emitter.h"
+#include "components/sync/engine_impl/cycle/data_type_debug_info_emitter.h"
 #include "components/sync/engine_impl/model_type_worker.h"
 #include "components/sync/nigori/cryptographer.h"
 #include "components/sync/nigori/keystore_keys_handler.h"
@@ -85,7 +85,7 @@
 
   DataTypeDebugInfoEmitter* emitter = GetEmitter(type);
   if (emitter == nullptr) {
-    auto new_emitter = std::make_unique<NonBlockingTypeDebugInfoEmitter>(type);
+    auto new_emitter = std::make_unique<DataTypeDebugInfoEmitter>(type);
     emitter = new_emitter.get();
     data_type_debug_info_emitter_map_.insert(
         std::make_pair(type, std::move(new_emitter)));
diff --git a/components/sync/engine_impl/model_type_worker.cc b/components/sync/engine_impl/model_type_worker.cc
index 18412d3..b743957 100644
--- a/components/sync/engine_impl/model_type_worker.cc
+++ b/components/sync/engine_impl/model_type_worker.cc
@@ -29,7 +29,7 @@
 #include "components/sync/engine/model_type_processor.h"
 #include "components/sync/engine_impl/bookmark_update_preprocessing.h"
 #include "components/sync/engine_impl/commit_contribution.h"
-#include "components/sync/engine_impl/non_blocking_type_commit_contribution.h"
+#include "components/sync/engine_impl/commit_contribution_impl.h"
 #include "components/sync/protocol/proto_memory_estimations.h"
 
 namespace syncer {
@@ -424,7 +424,7 @@
   }
 
   DCHECK(response.size() <= max_entries);
-  return std::make_unique<NonBlockingTypeCommitContribution>(
+  return std::make_unique<CommitContributionImpl>(
       GetModelType(), model_type_state_.type_context(), std::move(response),
       base::BindOnce(&ModelTypeWorker::OnCommitResponse,
                      weak_ptr_factory_.GetWeakPtr()),
diff --git a/components/sync/engine_impl/model_type_worker_unittest.cc b/components/sync/engine_impl/model_type_worker_unittest.cc
index 0139fb860..c6e21902 100644
--- a/components/sync/engine_impl/model_type_worker_unittest.cc
+++ b/components/sync/engine_impl/model_type_worker_unittest.cc
@@ -19,7 +19,7 @@
 #include "components/sync/base/unique_position.h"
 #include "components/sync/engine/model_type_processor.h"
 #include "components/sync/engine_impl/commit_contribution.h"
-#include "components/sync/engine_impl/cycle/non_blocking_type_debug_info_emitter.h"
+#include "components/sync/engine_impl/cycle/data_type_debug_info_emitter.h"
 #include "components/sync/engine_impl/cycle/status_controller.h"
 #include "components/sync/nigori/cryptographer_impl.h"
 #include "components/sync/nigori/nigori.h"
@@ -150,8 +150,7 @@
         mock_type_processor_(nullptr),
         mock_server_(std::make_unique<SingleTypeMockServer>(model_type)),
         is_processor_disconnected_(false),
-        emitter_(
-            std::make_unique<NonBlockingTypeDebugInfoEmitter>(model_type)) {}
+        emitter_(std::make_unique<DataTypeDebugInfoEmitter>(model_type)) {}
 
   ~ModelTypeWorkerTest() override {}
 
@@ -187,7 +186,7 @@
 
   void InitializeCommitOnly() {
     mock_server_ = std::make_unique<SingleTypeMockServer>(USER_EVENTS);
-    emitter_ = std::make_unique<NonBlockingTypeDebugInfoEmitter>(USER_EVENTS);
+    emitter_ = std::make_unique<DataTypeDebugInfoEmitter>(USER_EVENTS);
 
     // Don't set progress marker, commit only types don't use them.
     ModelTypeState initial_state;
@@ -470,7 +469,7 @@
   MockModelTypeProcessor* processor() { return mock_type_processor_; }
   ModelTypeWorker* worker() { return worker_.get(); }
   SingleTypeMockServer* server() { return mock_server_.get(); }
-  NonBlockingTypeDebugInfoEmitter* emitter() { return emitter_.get(); }
+  DataTypeDebugInfoEmitter* emitter() { return emitter_.get(); }
   MockNudgeHandler* nudge_handler() { return &mock_nudge_handler_; }
   StatusController* status_controller() { return &status_controller_; }
 
@@ -508,7 +507,7 @@
 
   bool is_processor_disconnected_;
 
-  std::unique_ptr<NonBlockingTypeDebugInfoEmitter> emitter_;
+  std::unique_ptr<DataTypeDebugInfoEmitter> emitter_;
 
   StatusController status_controller_;
 };
diff --git a/components/sync_bookmarks/bookmark_local_changes_builder.cc b/components/sync_bookmarks/bookmark_local_changes_builder.cc
index 2fd92ff..849ae46 100644
--- a/components/sync_bookmarks/bookmark_local_changes_builder.cc
+++ b/components/sync_bookmarks/bookmark_local_changes_builder.cc
@@ -70,7 +70,7 @@
       data->parent_id = parent_entity->metadata()->server_id();
       // TODO(crbug.com/516866): Double check that custom passphrase works well
       // with this implementation, because:
-      // 1. NonBlockingTypeCommitContribution::AdjustCommitProto() clears the
+      // 1. syncer::CommitContributionImpl::AdjustCommitProto() clears the
       //    title out.
       // 2. Bookmarks (maybe ancient legacy bookmarks only?) use/used |name| to
       //    encode the title.
diff --git a/components/translate/core/browser/mock_translate_client.h b/components/translate/core/browser/mock_translate_client.h
index ff8fef9..5e832f8 100644
--- a/components/translate/core/browser/mock_translate_client.h
+++ b/components/translate/core/browser/mock_translate_client.h
@@ -56,6 +56,7 @@
                     bool));
   MOCK_METHOD1(IsTranslatableURL, bool(const GURL&));
   MOCK_METHOD1(ShowReportLanguageDetectionErrorUI, void(const GURL&));
+  MOCK_CONST_METHOD0(IsAutofillAssistantRunning, bool());
 
  private:
   TranslateDriver* driver_;
diff --git a/components/translate/core/browser/translate_browser_metrics.h b/components/translate/core/browser/translate_browser_metrics.h
index 9ab317f..9c05723 100644
--- a/components/translate/core/browser/translate_browser_metrics.h
+++ b/components/translate/core/browser/translate_browser_metrics.h
@@ -43,6 +43,7 @@
   INITIATION_STATUS_NO_NETWORK,
   INITIATION_STATUS_DOESNT_NEED_TRANSLATION,
   INITIATION_STATUS_IDENTICAL_LANGUAGE_USE_SOURCE_LANGUAGE_UNKNOWN,
+  INITIATION_STATUS_DISABLED_BY_AUTOFILL_ASSISTANT,
   // Insert new items here.
   INITIATION_STATUS_MAX,
 };
diff --git a/components/translate/core/browser/translate_client.h b/components/translate/core/browser/translate_client.h
index 54ea538..bee78bd 100644
--- a/components/translate/core/browser/translate_client.h
+++ b/components/translate/core/browser/translate_client.h
@@ -74,6 +74,10 @@
   // a language detection error, to the user to allow them to report language
   // detection errors as desired.
   virtual void ShowReportLanguageDetectionErrorUI(const GURL& report_url) = 0;
+
+  // Returns if AutofillAssistant is running. Translation should be disabled
+  // while AutofillAssistant is running.
+  virtual bool IsAutofillAssistantRunning() const = 0;
 };
 
 }  // namespace translate
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc
index 9465177..c56cf74 100644
--- a/components/translate/core/browser/translate_manager.cc
+++ b/components/translate/core/browser/translate_manager.cc
@@ -177,6 +177,12 @@
                             target_lang);
 }
 
+void TranslateManager::InitiateTranslation() {
+  if (!page_language_code_.empty()) {
+    InitiateTranslation(page_language_code_);
+  }
+}
+
 // static
 std::string TranslateManager::GetManualTargetLanguage(
     const std::string& source_code,
@@ -735,6 +741,15 @@
         TranslateBrowserMetrics::INITIATION_STATUS_NO_NETWORK);
   }
 
+  // Skip translation if autofill assistant is running.
+  if (translate_client_->IsAutofillAssistantRunning()) {
+    page_language_code_ = page_language_code;
+    decision->PreventAllTriggering();
+    decision->initiation_statuses.push_back(
+        TranslateBrowserMetrics::
+            INITIATION_STATUS_DISABLED_BY_AUTOFILL_ASSISTANT);
+  }
+
   if (!ignore_missing_key_for_testing_ &&
       !::google_apis::HasAPIKeyConfigured()) {
     // Without an API key, translate won't work, so don't offer to translate in
diff --git a/components/translate/core/browser/translate_manager.h b/components/translate/core/browser/translate_manager.h
index 8620380..3ba10aa 100644
--- a/components/translate/core/browser/translate_manager.h
+++ b/components/translate/core/browser/translate_manager.h
@@ -124,6 +124,10 @@
   // Starts the translation process for the page in the |page_lang| language.
   void InitiateTranslation(const std::string& page_lang);
 
+  // Starts the translation process for the page in the |page_language_code|
+  // language.
+  void InitiateTranslation();
+
   // Initiate a manually triggered translation process for the current page.
   // Collect source and target languages, and show translation UI. If
   // |auto_translate| is true the page gets translated to the target language.
@@ -327,6 +331,11 @@
 
   std::unique_ptr<metrics::TranslateEventProto> translate_event_;
 
+  // Language code of current page. Code is remember when translation is
+  // disabled by Autofill Assistant. This code is later used to translate page
+  // when Autofill Assistant finishes run.
+  std::string page_language_code_;
+
   base::WeakPtrFactory<TranslateManager> weak_method_factory_{this};
 
   // By default, don't offer to translate in builds lacking an API key. For
diff --git a/components/translate/core/browser/translate_manager_unittest.cc b/components/translate/core/browser/translate_manager_unittest.cc
index 48a0c6d..acc3020 100644
--- a/components/translate/core/browser/translate_manager_unittest.cc
+++ b/components/translate/core/browser/translate_manager_unittest.cc
@@ -140,6 +140,8 @@
   void SetUp() override {
     // Ensure we're not requesting a server-side translate language list.
     TranslateLanguageList::DisableUpdate();
+    ON_CALL(mock_translate_client_, IsAutofillAssistantRunning)
+        .WillByDefault(Return(false));
 
     manager_->ResetForTesting();
   }
@@ -377,6 +379,8 @@
   ON_CALL(mock_translate_client_,
           ShowTranslateUI(_, _, _, _, false /* triggered_from_menu */))
       .WillByDefault(Return(true));
+  ON_CALL(mock_translate_client_, IsAutofillAssistantRunning())
+      .WillByDefault(Return(false));
 
   translate_manager_ = std::make_unique<translate::TranslateManager>(
       &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
@@ -721,6 +725,47 @@
                   Bucket(metrics::INITIATION_STATUS_AUTO_BY_LINK, 1))));
 }
 
+TEST_F(TranslateManagerTest, DontTranslateAutofillAssistantRunning) {
+  TranslateManager::SetIgnoreMissingKeyForTesting(true);
+
+  TranslateAcceptLanguages accept_languages(&prefs_, accept_languages_prefs);
+  ON_CALL(mock_translate_client_, GetTranslateAcceptLanguages())
+      .WillByDefault(Return(&accept_languages));
+  ON_CALL(mock_translate_client_, IsAutofillAssistantRunning())
+      .WillByDefault(Return(true));
+
+  translate_manager_ = std::make_unique<translate::TranslateManager>(
+      &mock_translate_client_, &mock_translate_ranker_, &mock_language_model_);
+
+  // The test measures that the "Translate was disabled" exit can only be
+  // reached after the early-out tests including IsOffline() passed.
+  base::HistogramTester histogram_tester;
+
+  prefs_.SetBoolean(prefs::kOfferTranslateEnabled, false);
+
+  translate_manager_->GetLanguageState()->LanguageDetermined("de", true);
+
+  // When Autofill assistant is running, Initiate won't trigger any translate
+  // behavior.
+  translate_manager_->InitiateTranslation("de");
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples(kInitiationStatusName),
+      ::testing::Contains(Bucket(
+          metrics::INITIATION_STATUS_DISABLED_BY_AUTOFILL_ASSISTANT, 1)));
+  EXPECT_THAT(histogram_tester.GetAllSamples(kInitiationStatusName),
+              ::testing::Not(::testing::Contains(
+                  Bucket(metrics::INITIATION_STATUS_SHOW_INFOBAR, 1))));
+  EXPECT_THAT(histogram_tester.GetAllSamples(kInitiationStatusName),
+              ::testing::Not(::testing::Contains(
+                  Bucket(metrics::INITIATION_STATUS_SHOW_ICON, 1))));
+  EXPECT_THAT(histogram_tester.GetAllSamples(kInitiationStatusName),
+              ::testing::Not(::testing::Contains(
+                  Bucket(metrics::INITIATION_STATUS_AUTO_BY_CONFIG, 1))));
+  EXPECT_THAT(histogram_tester.GetAllSamples(kInitiationStatusName),
+              ::testing::Not(::testing::Contains(
+                  Bucket(metrics::INITIATION_STATUS_AUTO_BY_LINK, 1))));
+}
+
 TEST_F(TranslateManagerTest, TestRecordTranslateEvent) {
   PrepareTranslateManager();
   const std::string locale = "zh-TW";
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index 904fd7d..1344081b6 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -394,10 +394,10 @@
   }
 #endif
 
-#if BUILDFLAG(USE_VAAPI)
+#if BUILDFLAG(USE_VAAPI_IMAGE_CODECS)
   image_decode_accelerator_worker_ =
       media::VaapiImageDecodeAcceleratorWorker::Create();
-#endif
+#endif  // BUILDFLAG(USE_VAAPI_IMAGE_CODECS)
 
 #if defined(OS_APPLE)
   if (gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_METAL] ==
diff --git a/components/webxr/android/BUILD.gn b/components/webxr/android/BUILD.gn
index 67d3785..013ce5de 100644
--- a/components/webxr/android/BUILD.gn
+++ b/components/webxr/android/BUILD.gn
@@ -7,8 +7,21 @@
 
 assert(enable_vr)
 
+source_set("android_utils") {
+  sources = [
+    "webxr_utils.cc",
+    "webxr_utils.h",
+  ]
+
+  deps = [
+    "//base",
+    "//content/public/browser",
+  ]
+}
+
 source_set("android") {
   sources = [
+    "xr_install_helper_delegate.h",
     "xr_install_infobar.cc",
     "xr_install_infobar.h",
   ]
@@ -21,6 +34,7 @@
   }
 
   deps = [
+    ":android_utils",
     "//base",
     "//components/infobars/core",
     "//components/resources:android_resources",
diff --git a/components/webxr/android/arcore_install_helper.cc b/components/webxr/android/arcore_install_helper.cc
index 4d2ea4f..99f1634 100644
--- a/components/webxr/android/arcore_install_helper.cc
+++ b/components/webxr/android/arcore_install_helper.cc
@@ -15,6 +15,8 @@
 #include "components/resources/android/theme_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/webxr/android/ar_jni_headers/ArCoreInstallUtils_jni.h"
+#include "components/webxr/android/webxr_utils.h"
+#include "components/webxr/android/xr_install_helper_delegate.h"
 #include "components/webxr/android/xr_install_infobar.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
@@ -22,29 +24,12 @@
 using base::android::AttachCurrentThread;
 
 namespace webxr {
-namespace {
-content::WebContents* GetWebContents(int render_process_id,
-                                     int render_frame_id) {
-  content::RenderFrameHost* render_frame_host =
-      content::RenderFrameHost::FromID(render_process_id, render_frame_id);
-  DCHECK(render_frame_host);
 
-  content::WebContents* web_contents =
-      content::WebContents::FromRenderFrameHost(render_frame_host);
-  DCHECK(web_contents);
+ArCoreInstallHelper::ArCoreInstallHelper(
+    std::unique_ptr<XrInstallHelperDelegate> install_delegate)
+    : install_delegate_(std::move(install_delegate)) {
+  DCHECK(install_delegate_);
 
-  return web_contents;
-}
-
-base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents(
-    int render_process_id,
-    int render_frame_id) {
-  return GetWebContents(render_process_id, render_frame_id)
-      ->GetJavaWebContents();
-}
-}  // namespace
-
-ArCoreInstallHelper::ArCoreInstallHelper() {
   // As per documentation, it's recommended to issue a call to
   // ArCoreApk.checkAvailability() early in application lifecycle & ignore the
   // result so that subsequent calls can return cached result:
@@ -71,7 +56,6 @@
 void ArCoreInstallHelper::EnsureInstalled(
     int render_process_id,
     int render_frame_id,
-    infobars::InfoBarManager* infobar_manager,
     base::OnceCallback<void(bool)> install_callback) {
   DCHECK(!install_finished_callback_);
   install_finished_callback_ = std::move(install_callback);
@@ -84,7 +68,7 @@
   // ARCore is not installed or requires an update.
   if (Java_ArCoreInstallUtils_shouldRequestInstallSupportedArCore(
           AttachCurrentThread())) {
-    ShowInfoBar(render_process_id, render_frame_id, infobar_manager);
+    ShowInfoBar(render_process_id, render_frame_id);
     return;
   }
 
@@ -93,10 +77,12 @@
   OnRequestInstallSupportedArCoreResult(nullptr, true);
 }
 
-void ArCoreInstallHelper::ShowInfoBar(
-    int render_process_id,
-    int render_frame_id,
-    infobars::InfoBarManager* infobar_manager) {
+void ArCoreInstallHelper::ShowInfoBar(int render_process_id,
+                                      int render_frame_id) {
+  infobars::InfoBarManager* infobar_manager =
+      install_delegate_->GetInfoBarManager(
+          GetWebContents(render_process_id, render_frame_id));
+
   // We can't show an infobar without an |infobar_manager|, so if it's null,
   // report that we are not installed and stop processing.
   if (!infobar_manager) {
diff --git a/components/webxr/android/arcore_install_helper.h b/components/webxr/android/arcore_install_helper.h
index 0497131..0813df34 100644
--- a/components/webxr/android/arcore_install_helper.h
+++ b/components/webxr/android/arcore_install_helper.h
@@ -5,16 +5,17 @@
 #ifndef COMPONENTS_WEBXR_ANDROID_ARCORE_INSTALL_HELPER_H_
 #define COMPONENTS_WEBXR_ANDROID_ARCORE_INSTALL_HELPER_H_
 
+#include <memory>
+
 #include "base/android/jni_android.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
-
-namespace infobars {
-class InfoBarManager;
-}
+#include "content/public/browser/xr_install_helper.h"
 
 namespace webxr {
+class XrInstallHelperDelegate;
+
 // Equivalent of ArCoreApk.Availability enum.
 // For detailed description, please see:
 // https://developers.google.com/ar/reference/java/arcore/reference/com/google/ar/core/ArCoreApk.Availability
@@ -29,26 +30,30 @@
   kUnsupportedDeviceNotCapable = 6,
 };
 
-class ArCoreInstallHelper {
+// Helper class to ensure that ArCore has been properly installed from the
+// store, per the ArCore Apk's installation implementation. Inherits from
+// content::XrInstallHelper so that it may be returned by the
+// XrIntegrationClient.
+class ArCoreInstallHelper : public content::XrInstallHelper {
  public:
-  ArCoreInstallHelper();
-  virtual ~ArCoreInstallHelper();
+  explicit ArCoreInstallHelper(
+      std::unique_ptr<XrInstallHelperDelegate> install_delegate);
+  ~ArCoreInstallHelper() override;
 
   ArCoreInstallHelper(const ArCoreInstallHelper&) = delete;
   ArCoreInstallHelper& operator=(const ArCoreInstallHelper&) = delete;
 
-  void EnsureInstalled(int render_process_id,
-                       int render_frame_id,
-                       infobars::InfoBarManager* infobar_manager,
-                       base::OnceCallback<void(bool)> install_callback);
+  // content::XrInstallHelper implementation.
+  void EnsureInstalled(
+      int render_process_id,
+      int render_frame_id,
+      base::OnceCallback<void(bool)> install_callback) override;
 
   // Called from Java end.
   void OnRequestInstallSupportedArCoreResult(JNIEnv* env, bool success);
 
  private:
-  void ShowInfoBar(int render_process_id,
-                   int render_frame_id,
-                   infobars::InfoBarManager* infobar_manager);
+  void ShowInfoBar(int render_process_id, int render_frame_id);
   void OnInfoBarResponse(int render_process_id,
                          int render_frame_id,
                          bool try_install);
@@ -56,6 +61,7 @@
 
   base::OnceCallback<void(bool)> install_finished_callback_;
   base::android::ScopedJavaGlobalRef<jobject> java_install_utils_;
+  std::unique_ptr<XrInstallHelperDelegate> install_delegate_;
 
   // Must be last.
   base::WeakPtrFactory<ArCoreInstallHelper> weak_ptr_factory_{this};
diff --git a/chrome/browser/android/vr/android_vr_utils.cc b/components/webxr/android/webxr_utils.cc
similarity index 90%
rename from chrome/browser/android/vr/android_vr_utils.cc
rename to components/webxr/android/webxr_utils.cc
index 4c96a9d..ed30801 100644
--- a/chrome/browser/android/vr/android_vr_utils.cc
+++ b/components/webxr/android/webxr_utils.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/android/vr/android_vr_utils.h"
+#include "components/webxr/android/webxr_utils.h"
 
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 
-namespace vr {
+namespace webxr {
 
 content::WebContents* GetWebContents(int render_process_id,
                                      int render_frame_id) {
@@ -29,4 +29,4 @@
       ->GetJavaWebContents();
 }
 
-}  // namespace vr
+}  // namespace webxr
diff --git a/chrome/browser/android/vr/android_vr_utils.h b/components/webxr/android/webxr_utils.h
similarity index 72%
rename from chrome/browser/android/vr/android_vr_utils.h
rename to components/webxr/android/webxr_utils.h
index eb5f2fa..762a309 100644
--- a/chrome/browser/android/vr/android_vr_utils.h
+++ b/components/webxr/android/webxr_utils.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ANDROID_VR_ANDROID_VR_UTILS_H_
-#define CHROME_BROWSER_ANDROID_VR_ANDROID_VR_UTILS_H_
+#ifndef COMPONENTS_WEBXR_ANDROID_WEBXR_UTILS_H_
+#define COMPONENTS_WEBXR_ANDROID_WEBXR_UTILS_H_
 
 #include "base/android/jni_android.h"
 
@@ -13,8 +13,8 @@
 
 // Functions in this file are currently GVR/ArCore specific functions. If other
 // platforms need the same function here, please move it to
-// chrome/browser/vr/*util.cc|h
-namespace vr {
+// components/webxr/*util.cc|h
+namespace webxr {
 
 content::WebContents* GetWebContents(int render_process_id,
                                      int render_frame_id);
@@ -23,6 +23,6 @@
     int render_process_id,
     int render_frame_id);
 
-}  // namespace vr
+}  // namespace webxr
 
-#endif  // CHROME_BROWSER_ANDROID_VR_ANDROID_VR_UTILS_H_
+#endif  // COMPONENTS_WEBXR_ANDROID_WEBXR_UTILS_H_
diff --git a/components/webxr/android/xr_install_helper_delegate.h b/components/webxr/android/xr_install_helper_delegate.h
new file mode 100644
index 0000000..4df3bc2
--- /dev/null
+++ b/components/webxr/android/xr_install_helper_delegate.h
@@ -0,0 +1,42 @@
+// 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_WEBXR_ANDROID_XR_INSTALL_HELPER_DELEGATE_H_
+#define COMPONENTS_WEBXR_ANDROID_XR_INSTALL_HELPER_DELEGATE_H_
+
+namespace content {
+class WebContents;
+}
+
+namespace infobars {
+class InfoBarManager;
+}
+
+namespace webxr {
+
+// Helper class for InstallHelpers to gain access to other components. Since the
+// InstallHelpers are intended to be plumbed through content/public's
+// XrIntegrationClient, they may not contain direct references to other
+// component types. This provides a means for embedders to pass accessors for
+// other component types to the InstallHelpers.
+class XrInstallHelperDelegate {
+ public:
+  virtual ~XrInstallHelperDelegate() = default;
+
+  XrInstallHelperDelegate(const XrInstallHelperDelegate&) = delete;
+  XrInstallHelperDelegate& operator=(const XrInstallHelperDelegate&) = delete;
+
+  // Gets the InfoBarManager for the provided web_contents, which can be used to
+  // display the installation confirmation message. It is acceptable to return
+  // a null InfoBarManager, but installation may fail after doing so.
+  virtual infobars::InfoBarManager* GetInfoBarManager(
+      content::WebContents* web_contents) = 0;
+
+ protected:
+  XrInstallHelperDelegate() = default;
+};
+
+}  // namespace webxr
+
+#endif  // COMPONENTS_WEBXR_ANDROID_XR_INSTALL_HELPER_DELEGATE_H_
diff --git a/components/webxr/android/xr_install_infobar.h b/components/webxr/android/xr_install_infobar.h
index 370e434..631bd864 100644
--- a/components/webxr/android/xr_install_infobar.h
+++ b/components/webxr/android/xr_install_infobar.h
@@ -16,6 +16,9 @@
 // control a ConfirmInfoBar.
 class XrInstallInfoBar : public ConfirmInfoBarDelegate {
  public:
+  // Constructor for XrInstallInfoBar, the callback is guaranteed to be called,
+  // if the InfoBar is accepted, cancelled, or dismissed. The Callback will be
+  // passed a bool indicating whether the result of the InfoBar was "accepted."
   XrInstallInfoBar(InfoBarIdentifier identifier,
                    int icon_id,
                    int message_id,
diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc
index 43ba6f18..c51b7566 100644
--- a/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -4190,9 +4190,9 @@
   image_name.Release();
   // Cllicking the image will change its name.
   EXPECT_HRESULT_SUCCEEDED(image_action->doAction(0));
-  AccessibilityNotificationWaiter waiter(
-      shell()->web_contents(), ui::kAXModeComplete,
-      ui::AXEventGenerator::Event::NAME_CHANGED);
+  AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                         ui::kAXModeComplete,
+                                         ax::mojom::Event::kTextChanged);
   waiter.WaitForNotification();
   EXPECT_HRESULT_SUCCEEDED(
       image->get_accName(childid_self, image_name.Receive()));
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc
index 1e727c6..6fc6d9a 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -248,7 +248,6 @@
     case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
     case ui::AXEventGenerator::Event::DROPEFFECT_CHANGED:
     case ui::AXEventGenerator::Event::EXPANDED:
-    case ui::AXEventGenerator::Event::EDITABLE_TEXT_CHANGED:
     case ui::AXEventGenerator::Event::ENABLED_CHANGED:
     case ui::AXEventGenerator::Event::FOCUS_CHANGED:
     case ui::AXEventGenerator::Event::FLOW_FROM_CHANGED:
diff --git a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
index b90e88ff..b95c41e 100644
--- a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
@@ -225,7 +225,6 @@
     case ui::AXEventGenerator::Event::CLASS_NAME_CHANGED:
     case ui::AXEventGenerator::Event::DESCRIBED_BY_CHANGED:
     case ui::AXEventGenerator::Event::DROPEFFECT_CHANGED:
-    case ui::AXEventGenerator::Event::EDITABLE_TEXT_CHANGED:
     case ui::AXEventGenerator::Event::FOCUS_CHANGED:
     case ui::AXEventGenerator::Event::FLOW_FROM_CHANGED:
     case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 0a45c3f..84c58c7 100644
--- a/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -424,7 +424,6 @@
     case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
     case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
     case ui::AXEventGenerator::Event::DROPEFFECT_CHANGED:
-    case ui::AXEventGenerator::Event::EDITABLE_TEXT_CHANGED:
     case ui::AXEventGenerator::Event::ENABLED_CHANGED:
     case ui::AXEventGenerator::Event::FOCUS_CHANGED:
     case ui::AXEventGenerator::Event::FLOW_FROM_CHANGED:
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc
index 81c472d..2ebf927 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -135,10 +135,7 @@
       FireWinAccessibilityEvent(EVENT_SYSTEM_SCROLLINGSTART, node);
       break;
     case ax::mojom::Event::kTextChanged:
-      // TODO(crbug.com/1049261) Remove when Views are exposed in the AXTree
-      // which will fire generated text-changed events.
-      if (!node->IsWebContent())
-        HandleTextChangedEvent(*node);
+      HandleTextChangedEvent(*node);
       break;
     case ax::mojom::Event::kTextSelectionChanged:
       HandleTextSelectionChangedEvent(*node);
@@ -240,9 +237,6 @@
     case ui::AXEventGenerator::Event::DROPEFFECT_CHANGED:
       HandleAriaPropertiesChangedEvent(*node);
       break;
-    case ui::AXEventGenerator::Event::EDITABLE_TEXT_CHANGED:
-      HandleTextChangedEvent(*node);
-      break;
     case ui::AXEventGenerator::Event::ENABLED_CHANGED:
       FireUiaPropertyChangedEvent(UIA_IsEnabledPropertyId, node);
       HandleAriaPropertiesChangedEvent(*node);
@@ -329,10 +323,7 @@
       HandleAriaPropertiesChangedEvent(*node);
       break;
     case ui::AXEventGenerator::Event::NAME_CHANGED:
-      if (ui::IsText(node->GetRole()))
-        HandleTextChangedEvent(*node);
-      else
-        FireUiaPropertyChangedEvent(UIA_NamePropertyId, node);
+      FireUiaPropertyChangedEvent(UIA_NamePropertyId, node);
       // Only fire name changes when the name comes from an attribute, otherwise
       // name changes are redundant with text removed/inserted events.
       if (node->GetData().GetNameFrom() != ax::mojom::NameFrom::kContents)
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index c646253..c5525ac 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -364,10 +364,8 @@
   RunHtmlTest(FILE_PATH_LITERAL("actions.html"));
 }
 
-// crbug.com/1135774. Flaky due to missing invalidation when adding or removing
-// a mouse button listener.
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
-                       DISABLED_AccessibilityAddClickListener) {
+                       AccessibilityAddClickListener) {
   RunHtmlTest(FILE_PATH_LITERAL("add-click-listener.html"));
 }
 
diff --git a/content/browser/power_monitor_browsertest.cc b/content/browser/power_monitor_browsertest.cc
index c0257b9..2f913785 100644
--- a/content/browser/power_monitor_browsertest.cc
+++ b/content/browser/power_monitor_browsertest.cc
@@ -70,10 +70,7 @@
   ~MockPowerMonitorMessageBroadcaster() override = default;
 
   void Bind(mojo::PendingReceiver<device::mojom::PowerMonitor> receiver) {
-    GetUIThreadTaskRunner({})->PostTask(
-        FROM_HERE,
-        base::BindOnce(&MockPowerMonitorMessageBroadcaster::BindOnMainThread,
-                       base::Unretained(this), std::move(receiver)));
+    receivers_.Add(this, std::move(receiver));
   }
 
   // device::mojom::PowerMonitor:
@@ -92,11 +89,6 @@
   }
 
  private:
-  void BindOnMainThread(
-      mojo::PendingReceiver<device::mojom::PowerMonitor> receiver) {
-    receivers_.Add(this, std::move(receiver));
-  }
-
   bool on_battery_power_ = false;
 
   mojo::ReceiverSet<device::mojom::PowerMonitor> receivers_;
@@ -130,16 +122,10 @@
     if (!r)
       return;
 
-    // We can receiver binding requests for the spare RenderProcessHost -- this
-    // might happen before the test has provided the |renderer_bound_closure_|.
-    if (renderer_bound_closure_) {
-      ++request_count_from_renderer_;
-      std::move(renderer_bound_closure_).Run();
-    } else {
-      DCHECK(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
-    }
-
-    power_monitor_message_broadcaster_.Bind(std::move(r));
+    GetUIThreadTaskRunner({})->PostTask(
+        FROM_HERE,
+        base::BindOnce(&PowerMonitorTest::BindForRendererOnMainThread,
+                       base::Unretained(this), std::move(r)));
   }
 
   void BindForNonRenderer(BrowserChildProcessHost* process_host,
@@ -148,28 +134,11 @@
     if (!r)
       return;
 
-    const int type = process_host->GetData().process_type;
-    if (type == PROCESS_TYPE_UTILITY) {
-      if (utility_bound_closure_) {
-        ++request_count_from_utility_;
-        std::move(utility_bound_closure_).Run();
-      }
-    } else if (type == PROCESS_TYPE_GPU) {
-      ++request_count_from_gpu_;
-
-      // We ignore null gpu_bound_closure_ here for two possible scenarios:
-      //  - TestRendererProcess and TestUtilityProcess also result in spinning
-      //    up GPU processes as a side effect, but they do not set valid
-      //    gpu_bound_closure_.
-      //  - As GPU process is started during setup of browser test suite, so
-      //    it's possible that TestGpuProcess execution may have not started
-      //    yet when the PowerMonitor bind request comes here, in such case
-      //    gpu_bound_closure_ will also be null.
-      if (gpu_bound_closure_)
-        std::move(gpu_bound_closure_).Run();
-    }
-
-    power_monitor_message_broadcaster_.Bind(std::move(r));
+    GetUIThreadTaskRunner({})->PostTask(
+        FROM_HERE,
+        base::BindOnce(&PowerMonitorTest::BindForNonRendererOnMainThread,
+                       base::Unretained(this),
+                       process_host->GetData().process_type, std::move(r)));
   }
 
  protected:
@@ -200,6 +169,46 @@
   }
 
  private:
+  void BindForRendererOnMainThread(
+      mojo::PendingReceiver<device::mojom::PowerMonitor> receiver) {
+    // We can receiver binding requests for the spare RenderProcessHost -- this
+    // might happen before the test has provided the |renderer_bound_closure_|.
+    if (renderer_bound_closure_) {
+      ++request_count_from_renderer_;
+      std::move(renderer_bound_closure_).Run();
+    } else {
+      DCHECK(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
+    }
+
+    power_monitor_message_broadcaster_.Bind(std::move(receiver));
+  }
+
+  void BindForNonRendererOnMainThread(
+      int process_type,
+      mojo::PendingReceiver<device::mojom::PowerMonitor> receiver) {
+    if (process_type == PROCESS_TYPE_UTILITY) {
+      if (utility_bound_closure_) {
+        ++request_count_from_utility_;
+        std::move(utility_bound_closure_).Run();
+      }
+    } else if (process_type == PROCESS_TYPE_GPU) {
+      ++request_count_from_gpu_;
+
+      // We ignore null gpu_bound_closure_ here for two possible scenarios:
+      //  - TestRendererProcess and TestUtilityProcess also result in spinning
+      //    up GPU processes as a side effect, but they do not set valid
+      //    gpu_bound_closure_.
+      //  - As GPU process is started during setup of browser test suite, so
+      //    it's possible that TestGpuProcess execution may have not started
+      //    yet when the PowerMonitor bind request comes here, in such case
+      //    gpu_bound_closure_ will also be null.
+      if (gpu_bound_closure_)
+        std::move(gpu_bound_closure_).Run();
+    }
+
+    power_monitor_message_broadcaster_.Bind(std::move(receiver));
+  }
+
   int request_count_from_renderer_ = 0;
   int request_count_from_utility_ = 0;
   int request_count_from_gpu_ = 0;
@@ -261,13 +270,8 @@
   // Verify utility process on_battery_power changed to false.
   VerifyPowerStateInChildProcess(power_monitor_utility.get(), false);
 }
-// This flakes on Linux TSan: http://crbug.com/1127374
-#if defined(THREAD_SANITIZER)
-#define MAYBE_TestGpuProcess DISABLED_TestGpuProcess
-#else
-#define MAYBE_TestGpuProcess TestGpuProcess
-#endif
-IN_PROC_BROWSER_TEST_F(PowerMonitorTest, MAYBE_TestGpuProcess) {
+
+IN_PROC_BROWSER_TEST_F(PowerMonitorTest, TestGpuProcess) {
   // As gpu process is started automatically during the setup period of browser
   // test suite, it may have already started and bound PowerMonitor interface to
   // Device Service before execution of this TestGpuProcess test. So here we
diff --git a/content/browser/renderer_host/navigator.cc b/content/browser/renderer_host/navigator.cc
index aad6596..8793218 100644
--- a/content/browser/renderer_host/navigator.cc
+++ b/content/browser/renderer_host/navigator.cc
@@ -137,9 +137,7 @@
   // Embedders might disable locking for WebUI URLs, which is bad idea, however
   // this method should take this into account.
   SiteInstanceImpl* site_instance = render_frame_host->GetSiteInstance();
-  SiteInfo site_info = SiteInstanceImpl::ComputeSiteInfo(
-      site_instance->GetIsolationContext(), url_info,
-      site_instance->GetCoopCoepCrossOriginIsolatedInfo());
+  SiteInfo site_info = site_instance->DeriveSiteInfo(url_info);
   bool should_lock_process = site_info.ShouldLockProcessToSite(
       site_instance->GetIsolationContext(), site_instance->IsGuest());
 
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
index 69e0321..a7c684e 100644
--- a/content/browser/renderer_host/render_frame_host_manager.cc
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -1853,9 +1853,14 @@
     // thus use the correct process.
     DCHECK_EQ(controller.GetBrowserContext(),
               current_instance_impl->GetBrowserContext());
-    const SiteInfo dest_site_info = SiteInstanceImpl::ComputeSiteInfo(
-        current_instance_impl->GetIsolationContext(), dest_url_info,
-        cross_origin_isolated_info);
+
+    // TODO(acolwell): Remove DCHECK once |cross_origin_isolated_info| has been
+    // moved into UrlInfo and becomes part of |dest_url_info|. The
+    // DeriveSiteInfo() call below is depending on the COOP/COEP info matching.
+    DCHECK(cross_origin_isolated_info ==
+           current_instance_impl->GetCoopCoepCrossOriginIsolatedInfo());
+    const SiteInfo dest_site_info =
+        current_instance_impl->DeriveSiteInfo(dest_url_info);
     bool use_process_per_site =
         RenderProcessHostImpl::ShouldUseProcessPerSite(
             current_instance_impl->GetBrowserContext(), dest_site_info) &&
diff --git a/content/browser/renderer_host/render_frame_host_manager_browsertest.cc b/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
index d749cc9e..1179a66d 100644
--- a/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
@@ -5935,6 +5935,8 @@
 IN_PROC_BROWSER_TEST_P(
     ProactivelySwapBrowsingInstancesCrossSiteReuseProcessTest,
     NavigationToSiteThatRequiresDedicatedProcess) {
+  if (AreAllSitesIsolatedForTesting())
+    return;
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
   GURL b_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
@@ -5971,6 +5973,8 @@
 IN_PROC_BROWSER_TEST_P(
     ProactivelySwapBrowsingInstancesCrossSiteReuseProcessTest,
     NavigationFromSiteThatRequiresDedicatedProcess) {
+  if (AreAllSitesIsolatedForTesting())
+    return;
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
   GURL b_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index c4df57d..62457ee 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -4112,8 +4112,10 @@
   // Do not allow sharing of guest hosts. This is to prevent bugs where guest
   // and non-guest storage gets mixed. In the future, we might consider
   // enabling the sharing of guests, in this case this check should be removed
-  // and InSameStoragePartition should handle the possible sharing.
-  if (host->IsForGuestsOnly())
+  // and InSameStoragePartition should handle the possible sharing. Also
+  // deny any attempt where a guest request tries to use a |host| that is not
+  // explicitly created for guests.
+  if (host->IsForGuestsOnly() || is_guest)
     return false;
 
   // Check whether the given host and the intended site_url will be using the
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_vk_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_aura_vk_browsertest.cc
index d9544f18..309df309 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_vk_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_vk_browsertest.cc
@@ -277,13 +277,11 @@
   const char kVirtualKeyboardDataURL[] =
       "data:text/html,<!DOCTYPE html>"
       "<script>"
-      "  let VKRect, x, y, width, height, numEvents = 0;"
+      "  let VKRect, numEvents = 0;"
       "  navigator.virtualKeyboard.overlaysContent = true;"
       "  navigator.virtualKeyboard.addEventListener('geometrychange',"
       "   evt => {"
       "     numEvents++;"
-      "     let r = evt.boundingRect;"
-      "     x = r.x; y = r.y; width = r.width; height = r.height;"
       "     VKRect = navigator.virtualKeyboard.boundingRect"
       "   }, false);"
       "</script>";
@@ -332,10 +330,6 @@
   const int expected_y = kKeyboardY - root_widget_origin.y();
 
   EXPECT_EQ(1, EvalJs(shell(), "numEvents"));
-  EXPECT_EQ(0, EvalJs(shell(), "x"));
-  EXPECT_EQ(expected_y, EvalJs(shell(), "y"));
-  EXPECT_EQ(expected_width, EvalJs(shell(), "width"));
-  EXPECT_EQ(kKeyboardHeight, EvalJs(shell(), "height"));
   EXPECT_EQ(0, EvalJs(shell(), "VKRect.x"));
   EXPECT_EQ(expected_y, EvalJs(shell(), "VKRect.y"));
   EXPECT_EQ(expected_width, EvalJs(shell(), "VKRect.width"));
@@ -343,10 +337,6 @@
 
   input_method_->GetMockKeyboardController()->NotifyObserversOnKeyboardHidden();
   EXPECT_EQ(2, EvalJs(shell(), "numEvents"));
-  EXPECT_EQ(0, EvalJs(shell(), "width"));
-  EXPECT_EQ(0, EvalJs(shell(), "height"));
-  EXPECT_EQ(0, EvalJs(shell(), "x"));
-  EXPECT_EQ(0, EvalJs(shell(), "y"));
   EXPECT_EQ(0, EvalJs(shell(), "VKRect.x"));
   EXPECT_EQ(0, EvalJs(shell(), "VKRect.y"));
   EXPECT_EQ(0, EvalJs(shell(), "VKRect.width"));
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index a3be72a..64603c5 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -348,8 +348,10 @@
   }
 
   void TearDownOnMainThread() override {
-    RunOnCoreThread(
-        base::BindOnce(&self::TearDownOnCoreThread, base::Unretained(this)));
+    base::RunLoop loop;
+    RunOnCoreThread(base::BindOnce(&self::TearDownOnCoreThread,
+                                   base::Unretained(this), loop.QuitClosure()));
+    loop.Run();
     wrapper_ = nullptr;
   }
 
@@ -368,7 +370,16 @@
   }
 
   virtual void SetUpOnCoreThread() {}
-  virtual void TearDownOnCoreThread() {}
+
+  virtual void TearDownOnCoreThread(base::OnceClosure callback) {
+    // Flush remote storage control so that all pending callbacks are executed.
+    wrapper()
+        ->context()
+        ->registry()
+        ->GetRemoteStorageControl()
+        .FlushForTesting();
+    std::move(callback).Run();
+  }
 
   ServiceWorkerContextWrapper* wrapper() { return wrapper_.get(); }
   ServiceWorkerContext* public_context() { return wrapper(); }
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc
index 4add86a..f92beb6 100644
--- a/content/browser/site_instance_impl.cc
+++ b/content/browser/site_instance_impl.cc
@@ -665,6 +665,23 @@
   return site_info_;
 }
 
+SiteInfo SiteInstanceImpl::DeriveSiteInfo(const UrlInfo& url_info,
+                                          bool is_related) {
+  if (IsGuest()) {
+    // Guests currently must stay in the same SiteInstance no matter what the
+    // information in |url_info| so we return the current SiteInfo.
+    return site_info_;
+  }
+
+  if (is_related) {
+    return browsing_instance_->GetSiteInfoForURL(
+        url_info, /* allow_default_instance */ true);
+  }
+
+  return ComputeSiteInfo(GetIsolationContext(), url_info,
+                         GetCoopCoepCrossOriginIsolatedInfo());
+}
+
 const ProcessLock SiteInstanceImpl::GetProcessLock() const {
   return ProcessLock(site_info_);
 }
@@ -724,11 +741,10 @@
   // Note: This call must return information that is identical to what
   // would be reported in the SiteInstance returned by
   // GetRelatedSiteInstance(url).
-  SiteInfo site_info = browsing_instance_->GetSiteInfoForURL(
-      url_info, /* allow_default_instance */ true);
+  SiteInfo site_info = DeriveSiteInfo(url_info, /* is_related= */ true);
 
   // If this is a default SiteInstance and the BrowsingInstance gives us a
-  // non-default site URL even when we explicitly allow the default SiteInstance
+  // non-default SiteInfo even when we explicitly allow the default SiteInstance
   // to be considered, then |url| does not belong in the same process as this
   // SiteInstance. This can happen when the
   // kProcessSharingWithDefaultSiteInstances feature is not enabled and the
@@ -752,10 +768,12 @@
       return true;
 
     // If there is no process but there is a site, then the process must have
-    // been discarded after we navigated away.  If the site URLs match, then it
-    // is safe to use this SiteInstance.
+    // been discarded after we navigated away.  If the SiteInfos match, then it
+    // is safe to use this SiteInstance unless it is a guest. Guests are a
+    // special case because we need to be consistent with the HasProcess() path
+    // and the IsSuitableHost() call below always returns false for guests.
     if (site_info_ == site_info)
-      return true;
+      return !IsGuest();
 
     // If the site URLs do not match, but neither this SiteInstance nor the
     // destination site_url require dedicated processes, then it is safe to use
diff --git a/content/browser/site_instance_impl.h b/content/browser/site_instance_impl.h
index 5ff7aa8..2a69510 100644
--- a/content/browser/site_instance_impl.h
+++ b/content/browser/site_instance_impl.h
@@ -392,6 +392,24 @@
   // GetSiteURL().
   const SiteInfo& GetSiteInfo();
 
+  // Derives a new SiteInfo based on this SiteInstance's current state, and
+  // the information provided in |url_info|. This function is slightly different
+  // than ComputeSiteInfo() because it takes into account information specific
+  // to this SiteInstance, like whether it is a guest or not, and changes its
+  // behavior accordingly.
+  // |is_related| - Controls the SiteInfo returned for non-guest SiteInstances.
+  //  Set to true if the caller wants the SiteInfo for an existing related
+  //  SiteInstance associated with |url_info|. This is identical to what you
+  //  would get from GetRelatedSiteInstanceImpl(url_info)->GetSiteInfo(). This
+  //  may return the SiteInfo for the default SiteInstance so callers must be
+  //  prepared to deal with that. If set to false, a SiteInfo created with
+  //  ComputeSiteInfo() is returned.
+  //
+  // For guest SiteInstances, |site_info_| is returned because guests are not
+  // allowed to derive new guest SiteInfos. All guest navigations must stay in
+  // the same SiteInstance with the same SiteInfo.
+  SiteInfo DeriveSiteInfo(const UrlInfo& url_info, bool is_related = false);
+
   // Returns a ProcessLock that can be used with SetProcessLock to lock a
   // process to this SiteInstance's SiteInfo. The ProcessLock relies heavily on
   // the SiteInfo's process_lock_url() for security decisions.
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index f1dbbf9..c983e5e 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2444,15 +2444,14 @@
   std::string autoplay_policy = media::GetEffectiveAutoplayPolicy(command_line);
   if (autoplay_policy == switches::autoplay::kNoUserGestureRequiredPolicy) {
     prefs.autoplay_policy =
-        blink::web_pref::AutoplayPolicy::kNoUserGestureRequired;
+        blink::mojom::AutoplayPolicy::kNoUserGestureRequired;
   } else if (autoplay_policy ==
              switches::autoplay::kUserGestureRequiredPolicy) {
-    prefs.autoplay_policy =
-        blink::web_pref::AutoplayPolicy::kUserGestureRequired;
+    prefs.autoplay_policy = blink::mojom::AutoplayPolicy::kUserGestureRequired;
   } else if (autoplay_policy ==
              switches::autoplay::kDocumentUserActivationRequiredPolicy) {
     prefs.autoplay_policy =
-        blink::web_pref::AutoplayPolicy::kDocumentUserActivationRequired;
+        blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired;
   } else {
     NOTREACHED();
   }
diff --git a/content/browser/xr/service/browser_xr_runtime_impl.cc b/content/browser/xr/service/browser_xr_runtime_impl.cc
index 2f18a475..808c420 100644
--- a/content/browser/xr/service/browser_xr_runtime_impl.cc
+++ b/content/browser/xr/service/browser_xr_runtime_impl.cc
@@ -338,10 +338,6 @@
   NOTREACHED();
 }
 
-bool BrowserXRRuntimeImpl::SupportsArBlendMode() {
-  return device_data_->is_ar_blend_mode_supported;
-}
-
 void BrowserXRRuntimeImpl::OnDisplayInfoChanged(
     device::mojom::VRDisplayInfoPtr vr_device_info) {
   bool had_display_info = !!display_info_;
diff --git a/content/browser/xr/service/browser_xr_runtime_impl.h b/content/browser/xr/service/browser_xr_runtime_impl.h
index dcdcf2c..46e9e9f5 100644
--- a/content/browser/xr/service/browser_xr_runtime_impl.h
+++ b/content/browser/xr/service/browser_xr_runtime_impl.h
@@ -48,7 +48,6 @@
 
   bool SupportsCustomIPD() const;
   bool SupportsNonEmulatedHeight() const;
-  bool SupportsArBlendMode();
 
   device::mojom::XRRuntime* GetRuntime() { return runtime_.get(); }
 
diff --git a/content/browser/xr/service/xr_runtime_manager_impl.cc b/content/browser/xr/service/xr_runtime_manager_impl.cc
index 5863c158..9182c46f 100644
--- a/content/browser/xr/service/xr_runtime_manager_impl.cc
+++ b/content/browser/xr/service/xr_runtime_manager_impl.cc
@@ -166,7 +166,7 @@
   BrowserXRRuntimeImpl* runtime = nullptr;
   switch (options->mode) {
     case device::mojom::XRSessionMode::kImmersiveAr:
-      runtime = GetImmersiveArRuntime();
+      runtime = GetRuntime(device::mojom::XRDeviceId::ARCORE_DEVICE_ID);
       break;
     case device::mojom::XRSessionMode::kImmersiveVr:
       runtime = GetImmersiveVrRuntime();
@@ -214,20 +214,9 @@
 }
 
 BrowserXRRuntimeImpl* XRRuntimeManagerImpl::GetImmersiveArRuntime() {
-#if defined(OS_ANDROID)
-  auto* arcore_runtime =
-      GetRuntime(device::mojom::XRDeviceId::ARCORE_DEVICE_ID);
-  if (arcore_runtime && arcore_runtime->SupportsArBlendMode())
-    return arcore_runtime;
-#endif
-
-#if BUILDFLAG(ENABLE_OPENXR)
-  auto* openxr = GetRuntime(device::mojom::XRDeviceId::OPENXR_DEVICE_ID);
-  if (openxr && openxr->SupportsArBlendMode())
-    return openxr;
-#endif
-
-  return nullptr;
+  device::mojom::XRSessionOptions options = {};
+  options.mode = device::mojom::XRSessionMode::kImmersiveAr;
+  return GetRuntimeForOptions(&options);
 }
 
 device::mojom::VRDisplayInfoPtr XRRuntimeManagerImpl::GetCurrentVRDisplayInfo(
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 75381ef..f7feec1 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -3080,7 +3080,9 @@
 
 void RenderFrameImpl::GetInterfaceProvider(
     mojo::PendingReceiver<service_manager::mojom::InterfaceProvider> receiver) {
-  interface_provider_receivers_.Add(this, std::move(receiver));
+  auto task_runner = GetTaskRunner(blink::TaskType::kInternalDefault);
+  DCHECK(task_runner);
+  interface_provider_receivers_.Add(this, std::move(receiver), task_runner);
 }
 
 void RenderFrameImpl::GetCanonicalUrlForSharing(
diff --git a/content/shell/common/shell_content_client.cc b/content/shell/common/shell_content_client.cc
index 7df0fd3..38df755 100644
--- a/content/shell/common/shell_content_client.cc
+++ b/content/shell/common/shell_content_client.cc
@@ -67,4 +67,10 @@
   return &origin_trial_policy_;
 }
 
+void ShellContentClient::AddAdditionalSchemes(Schemes* schemes) {
+#if defined(OS_ANDROID)
+  schemes->local_schemes.push_back(url::kContentScheme);
+#endif
+}
+
 }  // namespace content
diff --git a/content/shell/common/shell_content_client.h b/content/shell/common/shell_content_client.h
index b8da1bc4..c261c09 100644
--- a/content/shell/common/shell_content_client.h
+++ b/content/shell/common/shell_content_client.h
@@ -25,6 +25,7 @@
   base::RefCountedMemory* GetDataResourceBytes(int resource_id) override;
   gfx::Image& GetNativeImageNamed(int resource_id) override;
   blink::OriginTrialPolicy* GetOriginTrialPolicy() override;
+  void AddAdditionalSchemes(Schemes* schemes) override;
 
  private:
   ShellOriginTrialPolicy origin_trial_policy_;
diff --git a/content/test/data/accessibility/event/aria-selected-changed-expected-uia-win.txt b/content/test/data/accessibility/event/aria-selected-changed-expected-uia-win.txt
index 62ba3b8..b5c06a6 100644
--- a/content/test/data/accessibility/event/aria-selected-changed-expected-uia-win.txt
+++ b/content/test/data/accessibility/event/aria-selected-changed-expected-uia-win.txt
@@ -23,7 +23,6 @@
 SelectionItemIsSelected changed on role=combobox
 SelectionItemIsSelected changed on role=listitem, name=Select2, Option2
 SelectionItem_ElementSelected on role=listitem, name=Select2, Option2
-Text_TextChanged on role=document
 ValueValue changed on role=combobox
 === Start Continuation ===
 AriaProperties changed on role=option, name=DivSelect, Option1
diff --git a/content/test/data/accessibility/event/aria-selected-changed.html b/content/test/data/accessibility/event/aria-selected-changed.html
index ea9e31d..2de7db4 100644
--- a/content/test/data/accessibility/event/aria-selected-changed.html
+++ b/content/test/data/accessibility/event/aria-selected-changed.html
@@ -1,4 +1,5 @@
 <!--
+  @UIA-WIN-DENY:Text_TextChanged*
   @UIA-WIN-DENY:Invoke_Invoked*
 -->
 <!DOCTYPE html>
diff --git a/content/test/data/accessibility/event/css-flex-text-update-expected-uia-win.txt b/content/test/data/accessibility/event/css-flex-text-update-expected-uia-win.txt
index 92abc7ad..f40a3245 100644
--- a/content/test/data/accessibility/event/css-flex-text-update-expected-uia-win.txt
+++ b/content/test/data/accessibility/event/css-flex-text-update-expected-uia-win.txt
@@ -1 +1 @@
-Text_TextChanged on role=description, name=new
+Name changed on role=description, name=new
\ No newline at end of file
diff --git a/content/test/data/accessibility/event/description-change-indirect-expected-win.txt b/content/test/data/accessibility/event/description-change-indirect-expected-win.txt
index e7cd29c..1a48a4c 100644
--- a/content/test/data/accessibility/event/description-change-indirect-expected-win.txt
+++ b/content/test/data/accessibility/event/description-change-indirect-expected-win.txt
@@ -1,6 +1,6 @@
 EVENT_OBJECT_DESCRIPTIONCHANGE on <div> role=ROLE_SYSTEM_GROUPING
 EVENT_OBJECT_HIDE on role=ROLE_SYSTEM_STATICTEXT name="apples"
-EVENT_OBJECT_REORDER on <h1#title> role=ROLE_SYSTEM_GROUPING name="oranges" level=1
+EVENT_OBJECT_REORDER on <h1#title> role=H1 name="oranges" level=1
 EVENT_OBJECT_SHOW on role=ROLE_SYSTEM_STATICTEXT name="oranges"
-IA2_EVENT_TEXT_INSERTED on <h1#title> role=ROLE_SYSTEM_GROUPING name="oranges" level=1 new_text={'oranges' start=0 end=7}
-IA2_EVENT_TEXT_REMOVED on <h1#title> role=ROLE_SYSTEM_GROUPING name="oranges" level=1 old_text={'apples' start=0 end=6}
+IA2_EVENT_TEXT_INSERTED on <h1#title> role=H1 name="oranges" level=1 new_text={'oranges' start=0 end=7}
+IA2_EVENT_TEXT_REMOVED on <h1#title> role=H1 name="oranges" level=1 old_text={'apples' start=0 end=6}
diff --git a/content/test/data/accessibility/event/description-change-indirect.html b/content/test/data/accessibility/event/description-change-indirect.html
index 05d6d9a..65d8c3a0 100644
--- a/content/test/data/accessibility/event/description-change-indirect.html
+++ b/content/test/data/accessibility/event/description-change-indirect.html
@@ -1,6 +1,7 @@
 <!--
 @BLINK-ALLOW:description=*
 @WIN-ALLOW:description=*
+@UIA-WIN-DENY:Text_TextChanged*
 @MAC-ALLOW:AXDescription
 
 Due to a bug in Windows (fixed in Windows 10 19H1), events are raised
diff --git a/content/test/data/accessibility/event/description-change-no-relation-expected-win.txt b/content/test/data/accessibility/event/description-change-no-relation-expected-win.txt
index 86af8e58..9c59d24f 100644
--- a/content/test/data/accessibility/event/description-change-no-relation-expected-win.txt
+++ b/content/test/data/accessibility/event/description-change-no-relation-expected-win.txt
@@ -1 +1,2 @@
-EVENT_OBJECT_DESCRIPTIONCHANGE on <div#a> role=ROLE_SYSTEM_GROUPING
+EVENT_OBJECT_DESCRIPTIONCHANGE on <div#a> role=DIV
+
diff --git a/content/test/data/accessibility/event/description-change-no-relation.html b/content/test/data/accessibility/event/description-change-no-relation.html
index f05e75d..c7fe1c5 100644
--- a/content/test/data/accessibility/event/description-change-no-relation.html
+++ b/content/test/data/accessibility/event/description-change-no-relation.html
@@ -1,3 +1,6 @@
+<!--
+@UIA-WIN-DENY:Text_TextChanged*
+-->
 <!DOCTYPE html>
 <html>
 <body>
diff --git a/content/test/data/accessibility/event/description-change.html b/content/test/data/accessibility/event/description-change.html
index c080dc39..0a9e6c1 100644
--- a/content/test/data/accessibility/event/description-change.html
+++ b/content/test/data/accessibility/event/description-change.html
@@ -1,3 +1,6 @@
+<!--
+@UIA-WIN-DENY:Text_TextChanged*
+-->
 <!DOCTYPE html>
 <html>
 <body>
diff --git a/content/test/data/accessibility/event/input-type-text-value-changed-expected-uia-win.txt b/content/test/data/accessibility/event/input-type-text-value-changed-expected-uia-win.txt
deleted file mode 100644
index dc0f563..0000000
--- a/content/test/data/accessibility/event/input-type-text-value-changed-expected-uia-win.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Text_TextChanged on role=textbox
-ValueValue changed on role=textbox
diff --git a/content/test/data/accessibility/event/live-region-change-expected-uia-win.txt b/content/test/data/accessibility/event/live-region-change-expected-uia-win.txt
index 8d033423..ee7c679 100644
--- a/content/test/data/accessibility/event/live-region-change-expected-uia-win.txt
+++ b/content/test/data/accessibility/event/live-region-change-expected-uia-win.txt
@@ -1,3 +1,3 @@
 LiveRegionChanged on role=group
 LiveRegionChanged on role=group
-Text_TextChanged on role=description, name=After
+Name changed on role=description, name=After
diff --git a/content/test/data/accessibility/event/live-region-change.html b/content/test/data/accessibility/event/live-region-change.html
index caf272b..0624e55 100644
--- a/content/test/data/accessibility/event/live-region-change.html
+++ b/content/test/data/accessibility/event/live-region-change.html
@@ -1,3 +1,6 @@
+<!--
+@UIA-WIN-DENY:Text_TextChanged*
+-->
 <!DOCTYPE html>
 <html>
 <body>
diff --git a/content/test/data/accessibility/event/live-region-create.html b/content/test/data/accessibility/event/live-region-create.html
index a887b2a..5f09c9e 100644
--- a/content/test/data/accessibility/event/live-region-create.html
+++ b/content/test/data/accessibility/event/live-region-create.html
@@ -1,3 +1,6 @@
+<!--
+@UIA-WIN-DENY:Text_TextChanged*
+-->
 <!DOCTYPE html>
 <html>
 <body>
diff --git a/content/test/data/accessibility/event/menulist-collapse-expected-uia-win.txt b/content/test/data/accessibility/event/menulist-collapse-expected-uia-win.txt
index 0b3357b..f4d8873 100644
--- a/content/test/data/accessibility/event/menulist-collapse-expected-uia-win.txt
+++ b/content/test/data/accessibility/event/menulist-collapse-expected-uia-win.txt
@@ -4,5 +4,4 @@
 AriaProperties changed on role=combobox
 SelectionItemIsSelected changed on role=combobox
 SelectionItem_ElementRemovedFromSelection on role=combobox
-Text_TextChanged on role=document
 ValueValue changed on role=combobox
diff --git a/content/test/data/accessibility/event/menulist-collapse-next-expected-uia-win.txt b/content/test/data/accessibility/event/menulist-collapse-next-expected-uia-win.txt
index fa79854..5954885 100644
--- a/content/test/data/accessibility/event/menulist-collapse-next-expected-uia-win.txt
+++ b/content/test/data/accessibility/event/menulist-collapse-next-expected-uia-win.txt
@@ -6,5 +6,4 @@
 SelectionItemIsSelected changed on role=combobox
 SelectionItemIsSelected changed on role=listitem, name=Orange
 SelectionItem_ElementSelected on role=listitem, name=Orange
-Text_TextChanged on role=document
 ValueValue changed on role=combobox
diff --git a/content/test/data/accessibility/event/menulist-collapse-next.html b/content/test/data/accessibility/event/menulist-collapse-next.html
index 7ce1665..75d3377 100644
--- a/content/test/data/accessibility/event/menulist-collapse-next.html
+++ b/content/test/data/accessibility/event/menulist-collapse-next.html
@@ -1,3 +1,6 @@
+<!--
+@UIA-WIN-DENY:Text_TextChanged*
+-->
 <!DOCTYPE html>
 <html>
 <body>
diff --git a/content/test/data/accessibility/event/menulist-collapse.html b/content/test/data/accessibility/event/menulist-collapse.html
index bfa753f..48a41e45 100644
--- a/content/test/data/accessibility/event/menulist-collapse.html
+++ b/content/test/data/accessibility/event/menulist-collapse.html
@@ -1,3 +1,6 @@
+<!--
+@UIA-WIN-DENY:Text_TextChanged*
+-->
 <!DOCTYPE html>
 <html>
 <body>
diff --git a/content/test/data/accessibility/event/menulist-focus.html b/content/test/data/accessibility/event/menulist-focus.html
index 73ba0b0..bc5b9b0 100644
--- a/content/test/data/accessibility/event/menulist-focus.html
+++ b/content/test/data/accessibility/event/menulist-focus.html
@@ -1,3 +1,6 @@
+<!--
+@UIA-WIN-DENY:Text_TextChanged*
+-->
 <!DOCTYPE html>
 <html>
 <body>
diff --git a/content/test/data/accessibility/event/name-change-indirect.html b/content/test/data/accessibility/event/name-change-indirect.html
index 961b993..bb5d946c 100644
--- a/content/test/data/accessibility/event/name-change-indirect.html
+++ b/content/test/data/accessibility/event/name-change-indirect.html
@@ -1,4 +1,6 @@
 <!--
+@UIA-WIN-DENY:Text_TextChanged*
+
 Due to a bug in Windows (fixed in Windows 10 19H1), events are raised
 exactly twice for any in-proc off-thread event listeners.
 AccessibilityEventRecorderUia will try to filter duplicate events, but the
diff --git a/content/test/data/accessibility/event/name-change.html b/content/test/data/accessibility/event/name-change.html
index c2646d3..23f9899 100644
--- a/content/test/data/accessibility/event/name-change.html
+++ b/content/test/data/accessibility/event/name-change.html
@@ -1,3 +1,6 @@
+<!--
+@UIA-WIN-DENY:Text_TextChanged*
+-->
 <!DOCTYPE html>
 <html>
 <body>
diff --git a/content/test/data/accessibility/event/text-changed-expected-uia-win.txt b/content/test/data/accessibility/event/text-changed-expected-uia-win.txt
index 059b390..433c250 100644
--- a/content/test/data/accessibility/event/text-changed-expected-uia-win.txt
+++ b/content/test/data/accessibility/event/text-changed-expected-uia-win.txt
@@ -1,4 +1,4 @@
+Name changed on role=description, name=Modified Div
+Name changed on role=heading, name=h
 StructureChanged/ChildAdded on role=description, name=Modified Para
 StructureChanged/ChildRemoved on role=group, name=p
-Text_TextChanged on role=description, name=Modified Div
-Text_TextChanged on role=heading, name=h
diff --git a/device/vr/android/arcore/arcore_device.cc b/device/vr/android/arcore/arcore_device.cc
index 8b32589..f5e3f9c 100644
--- a/device/vr/android/arcore/arcore_device.cc
+++ b/device/vr/android/arcore/arcore_device.cc
@@ -76,9 +76,6 @@
   // it obvious if we're using this data instead of the actual values we get
   // from the output drawing surface.
   SetVRDisplayInfo(CreateVRDisplayInfo({16, 16}));
-
-  // ARCORE always support AR blend modes
-  SetArBlendModeSupported(true);
 }
 
 ArCoreDevice::~ArCoreDevice() {
@@ -106,7 +103,6 @@
     mojom::XRRuntime::RequestSessionCallback callback) {
   DVLOG(1) << __func__;
   DCHECK(IsOnMainThread());
-  DCHECK(options->mode == device::mojom::XRSessionMode::kImmersiveAr);
 
   if (HasExclusiveSession()) {
     DVLOG(1) << __func__ << ": Rejecting additional session request";
@@ -286,11 +282,6 @@
 
   config->supports_viewport_scaling = true;
 
-  // ARCORE only supports immersive-ar sessions
-  session->enviroment_blend_mode =
-      device::mojom::XREnvironmentBlendMode::kAlphaBlend;
-  session->interaction_mode = device::mojom::XRInteractionMode::kScreenSpace;
-
   std::move(deferred_callback)
       .Run(std::move(session), std::move(session_controller));
 }
diff --git a/device/vr/oculus/oculus_render_loop.cc b/device/vr/oculus/oculus_render_loop.cc
index 2db135e2..0e449b86 100644
--- a/device/vr/oculus/oculus_render_loop.cc
+++ b/device/vr/oculus/oculus_render_loop.cc
@@ -119,20 +119,7 @@
   ovr_frame_index_ = 0;
 }
 
-device::mojom::XREnvironmentBlendMode OculusRenderLoop::GetEnvironmentBlendMode(
-    device::mojom::XRSessionMode session_mode) {
-  DCHECK_EQ(session_mode, mojom::XRSessionMode::kImmersiveVr);
-  return device::mojom::XREnvironmentBlendMode::kOpaque;
-}
-
-device::mojom::XRInteractionMode OculusRenderLoop::GetInteractionMode(
-    device::mojom::XRSessionMode session_mode) {
-  DCHECK_EQ(session_mode, mojom::XRSessionMode::kImmersiveVr);
-  return device::mojom::XRInteractionMode::kWorldSpace;
-}
-
-void OculusRenderLoop::OnSessionStart()
-) {
+void OculusRenderLoop::OnSessionStart() {
   LogViewerType(VrViewerType::OCULUS_UNKNOWN);
 }
 
diff --git a/device/vr/oculus/oculus_render_loop.h b/device/vr/oculus/oculus_render_loop.h
index dfb2708..8b589d6 100644
--- a/device/vr/oculus/oculus_render_loop.h
+++ b/device/vr/oculus/oculus_render_loop.h
@@ -37,10 +37,6 @@
   bool PreComposite() override;
   bool SubmitCompositedFrame() override;
   void OnLayerBoundsChanged() override;
-  device::mojom::XREnvironmentBlendMode GetEnvironmentBlendMode(
-      device::mojom::XRSessionMode session_mode) override;
-  device::mojom::XRInteractionMode GetInteractionMode(
-      device::mojom::XRSessionMode session_mode) override;
 
   // Helpers to implement XRDeviceAbstraction:
   void CreateOvrSwapChain();
diff --git a/device/vr/openxr/openxr_api_wrapper.cc b/device/vr/openxr/openxr_api_wrapper.cc
index 1b48d1ec..ec50d61b 100644
--- a/device/vr/openxr/openxr_api_wrapper.cc
+++ b/device/vr/openxr/openxr_api_wrapper.cc
@@ -143,7 +143,8 @@
 }
 
 bool OpenXrApiWrapper::HasSystem() const {
-  return system_ != kInvalidSystem && view_configs_.size() == kNumViews;
+  return system_ != kInvalidSystem && view_configs_.size() == kNumViews &&
+         HasBlendMode();
 }
 
 bool OpenXrApiWrapper::HasBlendMode() const {
@@ -201,6 +202,8 @@
       instance_, system, kSupportedViewConfiguration, view_count, &view_count,
       view_configs.data()));
 
+  RETURN_IF_XR_FAILED(PickEnvironmentBlendMode(system));
+
   // Only assign the member variables on success. If any of the above XR calls
   // fail, the vector cleans up view_configs if necessary. system does not need
   // to be cleaned up because it is not allocated.
@@ -210,48 +213,32 @@
   return XR_SUCCESS;
 }
 
-device::mojom::XREnvironmentBlendMode OpenXrApiWrapper::GetMojoBlendMode(
-    XrEnvironmentBlendMode xr_blend_mode) {
-  switch (xr_blend_mode) {
-    case XR_ENVIRONMENT_BLEND_MODE_OPAQUE:
-      return device::mojom::XREnvironmentBlendMode::kOpaque;
-    case XR_ENVIRONMENT_BLEND_MODE_ADDITIVE:
-      return device::mojom::XREnvironmentBlendMode::kAdditive;
-    case XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND:
-      return device::mojom::XREnvironmentBlendMode::kAlphaBlend;
-    case XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM:
-      NOTREACHED();
+XrResult OpenXrApiWrapper::PickEnvironmentBlendMode(XrSystemId system) {
+  const std::array<XrEnvironmentBlendMode, 2> kSupportedBlendMode = {
+      XR_ENVIRONMENT_BLEND_MODE_ADDITIVE,
+      XR_ENVIRONMENT_BLEND_MODE_OPAQUE,
   };
-  return device::mojom::XREnvironmentBlendMode::kOpaque;
-}
-
-device::mojom::XREnvironmentBlendMode
-OpenXrApiWrapper::PickEnvironmentBlendModeForSession(
-    device::mojom::XRSessionMode session_mode) {
   DCHECK(HasInstance());
-  std::vector<XrEnvironmentBlendMode> supported_blend_modes =
-      GetSupportedBlendModes(instance_, system_);
 
-  DCHECK(supported_blend_modes.size() > 0);
+  uint32_t blend_mode_count;
+  RETURN_IF_XR_FAILED(xrEnumerateEnvironmentBlendModes(
+      instance_, system, kSupportedViewConfiguration, 0, &blend_mode_count,
+      nullptr));
 
-  blend_mode_ = supported_blend_modes[0];
+  std::vector<XrEnvironmentBlendMode> blend_modes(blend_mode_count);
+  RETURN_IF_XR_FAILED(xrEnumerateEnvironmentBlendModes(
+      instance_, system, kSupportedViewConfiguration, blend_mode_count,
+      &blend_mode_count, blend_modes.data()));
 
-  switch (session_mode) {
-    case device::mojom::XRSessionMode::kImmersiveVr:
-      if (base::Contains(supported_blend_modes,
-                         XR_ENVIRONMENT_BLEND_MODE_OPAQUE))
-        blend_mode_ = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
-      break;
-    case device::mojom::XRSessionMode::kImmersiveAr:
-      if (base::Contains(supported_blend_modes,
-                         XR_ENVIRONMENT_BLEND_MODE_ADDITIVE))
-        blend_mode_ = XR_ENVIRONMENT_BLEND_MODE_ADDITIVE;
-      break;
-    case device::mojom::XRSessionMode::kInline:
-      NOTREACHED();
+  auto* blend_mode_it =
+      std::find_first_of(kSupportedBlendMode.begin(), kSupportedBlendMode.end(),
+                         blend_modes.begin(), blend_modes.end());
+  if (blend_mode_it == kSupportedBlendMode.end()) {
+    return XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED;
   }
 
-  return GetMojoBlendMode(blend_mode_);
+  blend_mode_ = *blend_mode_it;
+  return XR_SUCCESS;
 }
 
 bool OpenXrApiWrapper::UpdateAndGetSessionEnded() {
diff --git a/device/vr/openxr/openxr_api_wrapper.h b/device/vr/openxr/openxr_api_wrapper.h
index e55d8e5..b04f621 100644
--- a/device/vr/openxr/openxr_api_wrapper.h
+++ b/device/vr/openxr/openxr_api_wrapper.h
@@ -70,9 +70,6 @@
       const base::RepeatingCallback<void(mojom::XRVisibilityState)>&
           visibility_changed_callback);
 
-  device::mojom::XREnvironmentBlendMode PickEnvironmentBlendModeForSession(
-      device::mojom::XRSessionMode session_mode);
-
   static void DEVICE_VR_EXPORT SetTestHook(VRTestHook* hook);
 
  private:
@@ -81,7 +78,7 @@
   void Uninitialize();
 
   XrResult InitializeSystem();
-  XrResult InitializeEnvironmentBlendMode(XrSystemId system);
+  XrResult PickEnvironmentBlendMode(XrSystemId system);
   XrResult ProcessEvents();
   void EnsureEventPolling();
 
@@ -108,9 +105,6 @@
   uint32_t GetRecommendedSwapchainSampleCount() const;
   XrResult UpdateStageBounds();
 
-  device::mojom::XREnvironmentBlendMode GetMojoBlendMode(
-      XrEnvironmentBlendMode xr_blend_mode);
-
   // The session is running only after xrBeginSession and before xrEndSession.
   // It is not considered running after creation but before xrBeginSession.
   bool session_running_;
diff --git a/device/vr/openxr/openxr_device.cc b/device/vr/openxr/openxr_device.cc
index 3282dc89..bab86430 100644
--- a/device/vr/openxr/openxr_device.cc
+++ b/device/vr/openxr/openxr_device.cc
@@ -61,7 +61,7 @@
       weak_ptr_factory_(this) {
   mojom::VRDisplayInfoPtr display_info = CreateFakeVRDisplayInfo();
   SetVRDisplayInfo(std::move(display_info));
-  SetArBlendModeSupported(IsArBlendModeSupported(openxr_statics));
+
 #if defined(OS_WIN)
   SetLuid(openxr_statics->GetLuid());
 #endif
@@ -93,6 +93,7 @@
 void OpenXrDevice::RequestSession(
     mojom::XRRuntimeSessionOptionsPtr options,
     mojom::XRRuntime::RequestSessionCallback callback) {
+  DCHECK_EQ(options->mode, mojom::XRSessionMode::kImmersiveVr);
   EnsureRenderLoop();
 
   if (!render_loop_->IsRunning()) {
@@ -184,18 +185,4 @@
   }
 }
 
-bool OpenXrDevice::IsArBlendModeSupported(OpenXrStatics* openxr_statics) {
-  XrSystemId system;
-  if (XR_FAILED(GetSystem(openxr_statics->GetXrInstance(), &system)))
-    return false;
-
-  std::vector<XrEnvironmentBlendMode> environment_blend_modes =
-      GetSupportedBlendModes(openxr_statics->GetXrInstance(), system);
-
-  return base::Contains(environment_blend_modes,
-                        XR_ENVIRONMENT_BLEND_MODE_ADDITIVE) ||
-         base::Contains(environment_blend_modes,
-                        XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND);
-}
-
 }  // namespace device
diff --git a/device/vr/openxr/openxr_device.h b/device/vr/openxr/openxr_device.h
index 1ee325d..a20e5af 100644
--- a/device/vr/openxr/openxr_device.h
+++ b/device/vr/openxr/openxr_device.h
@@ -50,7 +50,6 @@
                               bool result,
                               mojom::XRSessionPtr session);
   void OnPresentingControllerMojoConnectionError();
-  bool IsArBlendModeSupported(OpenXrStatics* openxr_statics);
 
   XrInstance instance_;
   std::unique_ptr<OpenXrRenderLoop> render_loop_;
diff --git a/device/vr/openxr/openxr_render_loop.cc b/device/vr/openxr/openxr_render_loop.cc
index d4e79fca..de8f53b 100644
--- a/device/vr/openxr/openxr_render_loop.cc
+++ b/device/vr/openxr/openxr_render_loop.cc
@@ -132,16 +132,6 @@
   texture_helper_.Reset();
 }
 
-device::mojom::XREnvironmentBlendMode OpenXrRenderLoop::GetEnvironmentBlendMode(
-    device::mojom::XRSessionMode session_mode) {
-  return openxr_->PickEnvironmentBlendModeForSession(session_mode);
-}
-
-device::mojom::XRInteractionMode OpenXrRenderLoop::GetInteractionMode(
-    device::mojom::XRSessionMode session_mode) {
-  return device::mojom::XRInteractionMode::kWorldSpace;
-}
-
 void OpenXrRenderLoop::OnSessionStart() {
   LogViewerType(VrViewerType::OPENXR_UNKNOWN);
 }
diff --git a/device/vr/openxr/openxr_render_loop.h b/device/vr/openxr/openxr_render_loop.h
index 3f8259a4..2082cf1 100644
--- a/device/vr/openxr/openxr_render_loop.h
+++ b/device/vr/openxr/openxr_render_loop.h
@@ -39,10 +39,6 @@
   bool PreComposite() override;
   bool HasSessionEnded() override;
   bool SubmitCompositedFrame() override;
-  device::mojom::XREnvironmentBlendMode GetEnvironmentBlendMode(
-      device::mojom::XRSessionMode session_mode) override;
-  device::mojom::XRInteractionMode GetInteractionMode(
-      device::mojom::XRSessionMode session_mode) override;
 
   void InitializeDisplayInfo();
   bool UpdateEyeParameters();
diff --git a/device/vr/openxr/openxr_util.cc b/device/vr/openxr/openxr_util.cc
index e5fcbf1..82d3806 100644
--- a/device/vr/openxr/openxr_util.cc
+++ b/device/vr/openxr/openxr_util.cc
@@ -158,24 +158,4 @@
   return xrCreateInstance(&instance_create_info, instance);
 }
 
-std::vector<XrEnvironmentBlendMode> GetSupportedBlendModes(XrInstance instance,
-                                                           XrSystemId system) {
-  // Query the list of supported environment blend modes for the current system.
-  uint32_t blend_mode_count;
-  const XrViewConfigurationType kSupportedViewConfiguration =
-      XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
-  if (XR_FAILED(xrEnumerateEnvironmentBlendModes(instance, system,
-                                                 kSupportedViewConfiguration, 0,
-                                                 &blend_mode_count, nullptr)))
-    return {};  // empty vector
-
-  std::vector<XrEnvironmentBlendMode> environment_blend_modes(blend_mode_count);
-  if (XR_FAILED(xrEnumerateEnvironmentBlendModes(
-          instance, system, kSupportedViewConfiguration, blend_mode_count,
-          &blend_mode_count, environment_blend_modes.data())))
-    return {};  // empty vector
-
-  return environment_blend_modes;
-}
-
 }  // namespace device
diff --git a/device/vr/openxr/openxr_util.h b/device/vr/openxr/openxr_util.h
index dd3ec51..31d55162 100644
--- a/device/vr/openxr/openxr_util.h
+++ b/device/vr/openxr/openxr_util.h
@@ -60,9 +60,6 @@
 
 XrResult CreateInstance(XrInstance* instance);
 
-std::vector<XrEnvironmentBlendMode> GetSupportedBlendModes(XrInstance instance,
-                                                           XrSystemId system);
-
 }  // namespace device
 
 #endif  // DEVICE_VR_OPENXR_OPENXR_UTIL_H_
diff --git a/device/vr/orientation/orientation_device.cc b/device/vr/orientation/orientation_device.cc
index 400d7ee..bd7d124 100644
--- a/device/vr/orientation/orientation_device.cc
+++ b/device/vr/orientation/orientation_device.cc
@@ -140,9 +140,6 @@
     session->display_info = display_info_.Clone();
   }
   session->device_config = device::mojom::XRSessionDeviceConfig::New();
-  session->enviroment_blend_mode =
-      device::mojom::XREnvironmentBlendMode::kOpaque;
-  session->interaction_mode = device::mojom::XRInteractionMode::kScreenSpace;
 
   std::move(callback).Run(std::move(session), std::move(controller));
 
diff --git a/device/vr/public/mojom/isolated_xr_service.mojom b/device/vr/public/mojom/isolated_xr_service.mojom
index ca43122..842ad986 100644
--- a/device/vr/public/mojom/isolated_xr_service.mojom
+++ b/device/vr/public/mojom/isolated_xr_service.mojom
@@ -132,8 +132,6 @@
   [EnableIf=is_win]
   // The LUID of the GPU that the device is plugged into.
   gpu.mojom.Luid? luid;
-  // Indicates whether the device supports AR or not
-  bool is_ar_blend_mode_supported;
 };
 
 // Notify the browser process about a set of runtimes.  The browser process
diff --git a/device/vr/public/mojom/vr_service.mojom b/device/vr/public/mojom/vr_service.mojom
index 049acce1..a13a118 100644
--- a/device/vr/public/mojom/vr_service.mojom
+++ b/device/vr/public/mojom/vr_service.mojom
@@ -87,27 +87,6 @@
   kImmersiveAr = 3,
 };
 
-// These enum names come from the WebXR spec:
-// https://immersive-web.github.io/webxr-ar-module/#enumdef-xrenvironmentblendmode
-// When presenting content to the XR device, the XR Compositor MUST apply the
-// appropriate blend technique to combine virtual pixels with the
-// real-world environment.
-enum XREnvironmentBlendMode {
-  kOpaque = 1,
-  kAlphaBlend = 2,
-  kAdditive = 3,
-};
-
-// These enum names come from the WebXR spec:
-// https://immersive-web.github.io/webxr-ar-module/#enumdef-xrinteractionmode
-// The interactionMode attribute describes the best space
-// (according to the user agent) for the application to draw interactive
-// UI for the current session.
-enum XRInteractionMode {
-  kScreenSpace = 1,
-  kWorldSpace = 2,
-};
-
 struct XRSessionOptions {
   // Represents the type of session that is being requested.
   XRSessionMode mode;
@@ -168,9 +147,6 @@
 
   // Description of the device's active configuration.
   XRSessionDeviceConfig device_config;
-
-  XREnvironmentBlendMode enviroment_blend_mode;
-  XRInteractionMode interaction_mode;
 };
 
 // This structure contains the infomation and interfaces needed to create a two
diff --git a/device/vr/vr_device_base.cc b/device/vr/vr_device_base.cc
index 45f4a4a2..d72cb09 100644
--- a/device/vr/vr_device_base.cc
+++ b/device/vr/vr_device_base.cc
@@ -11,9 +11,7 @@
 
 namespace device {
 
-VRDeviceBase::VRDeviceBase(mojom::XRDeviceId id) : id_(id) {
-  device_data_.is_ar_blend_mode_supported = false;
-}
+VRDeviceBase::VRDeviceBase(mojom::XRDeviceId id) : id_(id) {}
 
 VRDeviceBase::~VRDeviceBase() = default;
 
@@ -80,10 +78,6 @@
     listener_->OnVisibilityStateChanged(visibility_state);
 }
 
-void VRDeviceBase::SetArBlendModeSupported(bool is_ar_blend_mode_supported) {
-  device_data_.is_ar_blend_mode_supported = is_ar_blend_mode_supported;
-}
-
 #if defined(OS_WIN)
 void VRDeviceBase::SetLuid(const LUID& luid) {
   if (luid.HighPart != 0 || luid.LowPart != 0) {
diff --git a/device/vr/vr_device_base.h b/device/vr/vr_device_base.h
index 7ed5d64..b5e9ef8 100644
--- a/device/vr/vr_device_base.h
+++ b/device/vr/vr_device_base.h
@@ -62,7 +62,6 @@
   bool IsPresenting() { return presenting_; }  // Exposed for test.
   void SetVRDisplayInfo(mojom::VRDisplayInfoPtr display_info);
   void OnVisibilityStateChanged(mojom::XRVisibilityState visibility_state);
-  void SetArBlendModeSupported(bool is_ar_blend_mode_supported);
 #if defined(OS_WIN)
   void SetLuid(const LUID& luid);
 #endif
diff --git a/device/vr/windows/compositor_base.cc b/device/vr/windows/compositor_base.cc
index 7990d64..b2bdc98 100644
--- a/device/vr/windows/compositor_base.cc
+++ b/device/vr/windows/compositor_base.cc
@@ -44,15 +44,6 @@
   return false;
 }
 void XRDeviceAbstraction::OnLayerBoundsChanged() {}
-device::mojom::XREnvironmentBlendMode
-XRDeviceAbstraction::GetEnvironmentBlendMode(
-    device::mojom::XRSessionMode session_mode) {
-  return device::mojom::XREnvironmentBlendMode::kOpaque;
-}
-device::mojom::XRInteractionMode XRDeviceAbstraction::GetInteractionMode(
-    device::mojom::XRSessionMode session_mode) {
-  return device::mojom::XRInteractionMode::kWorldSpace;
-}
 
 XRCompositorCommon::OutstandingFrame::OutstandingFrame() = default;
 XRCompositorCommon::OutstandingFrame::~OutstandingFrame() = default;
@@ -199,6 +190,7 @@
         on_visibility_state_changed,
     mojom::XRRuntimeSessionOptionsPtr options,
     RequestSessionCallback callback) {
+  DCHECK_EQ(options->mode, mojom::XRSessionMode::kImmersiveVr);
   webxr_has_pose_ = false;
   presentation_receiver_.reset();
   frame_data_receiver_.reset();
@@ -250,8 +242,6 @@
 
   session->device_config = device::mojom::XRSessionDeviceConfig::New();
   session->device_config->uses_input_eventing = UsesInputEventing();
-  session->enviroment_blend_mode = GetEnvironmentBlendMode(options->mode);
-  session->interaction_mode = GetInteractionMode(options->mode);
 
   main_thread_task_runner_->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true, std::move(session)));
diff --git a/device/vr/windows/compositor_base.h b/device/vr/windows/compositor_base.h
index 65cb7780..375fc12 100644
--- a/device/vr/windows/compositor_base.h
+++ b/device/vr/windows/compositor_base.h
@@ -39,10 +39,6 @@
   virtual bool SubmitCompositedFrame() = 0;
   virtual void HandleDeviceLost();
   virtual void OnLayerBoundsChanged();
-  virtual device::mojom::XREnvironmentBlendMode GetEnvironmentBlendMode(
-      device::mojom::XRSessionMode session_mode);
-  virtual device::mojom::XRInteractionMode GetInteractionMode(
-      device::mojom::XRSessionMode session_mode);
 };
 
 class XRCompositorCommon : public base::Thread,
diff --git a/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc b/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc
index a67dead..77d83ab1 100644
--- a/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc
+++ b/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc
@@ -471,19 +471,6 @@
   bounds_updated_ = (bounds_.size() != 0);
 }
 
-device::mojom::XREnvironmentBlendMode
-MixedRealityRenderLoop::GetEnvironmentBlendMode(
-    device::mojom::XRSessionMode session_mode) {
-  DCHECK_EQ(session_mode, mojom::XRSessionMode::kImmersiveVr);
-  return device::mojom::XREnvironmentBlendMode::kOpaque;
-}
-
-device::mojom::XRInteractionMode MixedRealityRenderLoop::GetInteractionMode(
-    device::mojom::XRSessionMode session_mode) {
-  DCHECK_EQ(session_mode, mojom::XRSessionMode::kImmersiveVr);
-  return device::mojom::XRInteractionMode::kWorldSpace;
-}
-
 void MixedRealityRenderLoop::OnSessionStart() {
   LogViewerType(VrViewerType::WINDOWS_MIXED_REALITY_UNKNOWN);
 
diff --git a/device/vr/windows_mixed_reality/mixed_reality_renderloop.h b/device/vr/windows_mixed_reality/mixed_reality_renderloop.h
index fe4584f..512478b 100644
--- a/device/vr/windows_mixed_reality/mixed_reality_renderloop.h
+++ b/device/vr/windows_mixed_reality/mixed_reality_renderloop.h
@@ -54,10 +54,6 @@
   void StopRuntime() override;
   void OnSessionStart() override;
   bool UsesInputEventing() override;
-  device::mojom::XREnvironmentBlendMode GetEnvironmentBlendMode(
-      device::mojom::XRSessionMode session_mode) override;
-  device::mojom::XRInteractionMode GetInteractionMode(
-      device::mojom::XRSessionMode session_mode) override;
 
   // XRDeviceAbstraction:
   mojom::XRFrameDataPtr GetNextFrameData() override;
diff --git a/extensions/browser/api/declarative_net_request/declarative_net_request_api.cc b/extensions/browser/api/declarative_net_request/declarative_net_request_api.cc
index a8f7caf..474c276 100644
--- a/extensions/browser/api/declarative_net_request/declarative_net_request_api.cc
+++ b/extensions/browser/api/declarative_net_request/declarative_net_request_api.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/feature_list.h"
 #include "base/optional.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
@@ -17,9 +18,11 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/api/declarative_net_request/action_tracker.h"
+#include "extensions/browser/api/declarative_net_request/composite_matcher.h"
 #include "extensions/browser/api/declarative_net_request/constants.h"
 #include "extensions/browser/api/declarative_net_request/rules_monitor_service.h"
 #include "extensions/browser/api/declarative_net_request/ruleset_manager.h"
+#include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
 #include "extensions/browser/api/declarative_net_request/ruleset_source.h"
 #include "extensions/browser/api/declarative_net_request/utils.h"
 #include "extensions/browser/api/extensions_api_client.h"
@@ -61,6 +64,23 @@
   return can_call;
 }
 
+size_t GetEnabledStaticRuleCount(
+    const declarative_net_request::CompositeMatcher* composite_matcher) {
+  size_t enabled_static_rule_count = 0;
+
+  if (composite_matcher) {
+    for (const std::unique_ptr<declarative_net_request::RulesetMatcher>&
+             matcher : composite_matcher->matchers()) {
+      if (matcher->id() == declarative_net_request::kDynamicRulesetID)
+        continue;
+
+      enabled_static_rule_count += matcher->GetRulesCount();
+    }
+  }
+
+  return enabled_static_rule_count;
+}
+
 }  // namespace
 
 DeclarativeNetRequestUpdateDynamicRulesFunction::
@@ -415,4 +435,57 @@
       ArgumentList(dnr_api::IsRegexSupported::Results::Create(result)));
 }
 
+DeclarativeNetRequestGetAvailableStaticRuleCountFunction::
+    DeclarativeNetRequestGetAvailableStaticRuleCountFunction() = default;
+DeclarativeNetRequestGetAvailableStaticRuleCountFunction::
+    ~DeclarativeNetRequestGetAvailableStaticRuleCountFunction() = default;
+
+ExtensionFunction::ResponseAction
+DeclarativeNetRequestGetAvailableStaticRuleCountFunction::Run() {
+  auto* rules_monitor_service =
+      declarative_net_request::RulesMonitorService::Get(browser_context());
+  DCHECK(rules_monitor_service);
+
+  declarative_net_request::CompositeMatcher* composite_matcher =
+      rules_monitor_service->ruleset_manager()->GetMatcherForExtension(
+          extension_id());
+
+  // First get the total enabled static rule count for the extension.
+  size_t enabled_static_rule_count =
+      GetEnabledStaticRuleCount(composite_matcher);
+  size_t static_rule_limit =
+      static_cast<size_t>(declarative_net_request::GetStaticRuleLimit());
+  DCHECK_LE(enabled_static_rule_count, static_rule_limit);
+
+  size_t available_static_rule_count = 0;
+  if (!base::FeatureList::IsEnabled(
+          declarative_net_request::kDeclarativeNetRequestGlobalRules)) {
+    available_static_rule_count = static_rule_limit - enabled_static_rule_count;
+    DCHECK_GE(static_rule_limit, available_static_rule_count);
+
+    return RespondNow(OneArgument(std::make_unique<base::Value>(
+        static_cast<int>(available_static_rule_count))));
+  }
+
+  const declarative_net_request::GlobalRulesTracker& global_rules_tracker =
+      rules_monitor_service->global_rules_tracker();
+
+  available_static_rule_count = global_rules_tracker.GetUnallocatedRuleCount();
+
+  // If an extension's rule count is below the guaranteed minimum, include the
+  // difference.
+  size_t guaranteed_static_minimum =
+      declarative_net_request::GetStaticGuaranteedMinimumRuleCount();
+  if (enabled_static_rule_count < guaranteed_static_minimum) {
+    available_static_rule_count +=
+        (guaranteed_static_minimum - enabled_static_rule_count);
+  }
+
+  // Ensure conversion to int below doesn't underflow.
+  DCHECK_LE(available_static_rule_count,
+            static_cast<size_t>(std::numeric_limits<int>::max()));
+  return RespondNow(OneArgument(std::make_unique<base::Value>(
+      static_cast<int>(available_static_rule_count))));
+}
+
 }  // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/declarative_net_request_api.h b/extensions/browser/api/declarative_net_request/declarative_net_request_api.h
index 496d9dc..82a1d3a 100644
--- a/extensions/browser/api/declarative_net_request/declarative_net_request_api.h
+++ b/extensions/browser/api/declarative_net_request/declarative_net_request_api.h
@@ -131,6 +131,21 @@
   ExtensionFunction::ResponseAction Run() override;
 };
 
+class DeclarativeNetRequestGetAvailableStaticRuleCountFunction
+    : public ExtensionFunction {
+ public:
+  DeclarativeNetRequestGetAvailableStaticRuleCountFunction();
+  DECLARE_EXTENSION_FUNCTION(
+      "declarativeNetRequest.getAvailableStaticRuleCount",
+      DECLARATIVENETREQUEST_GETAVAILABLESTATICRULECOUNT)
+
+ protected:
+  ~DeclarativeNetRequestGetAvailableStaticRuleCountFunction() override;
+
+  // ExtensionFunction override:
+  ExtensionFunction::ResponseAction Run() override;
+};
+
 }  // namespace extensions
 
 #endif  // EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_DECLARATIVE_NET_REQUEST_API_H_
diff --git a/extensions/browser/api/declarative_net_request/global_rules_tracker.cc b/extensions/browser/api/declarative_net_request/global_rules_tracker.cc
index 0e47a18c..637b8891 100644
--- a/extensions/browser/api/declarative_net_request/global_rules_tracker.cc
+++ b/extensions/browser/api/declarative_net_request/global_rules_tracker.cc
@@ -127,13 +127,16 @@
   return true;
 }
 
+size_t GlobalRulesTracker::GetUnallocatedRuleCount() const {
+  return GetGlobalStaticRuleLimit() - allocated_global_rule_count_;
+}
+
 size_t GlobalRulesTracker::GetAvailableAllocation(
     const ExtensionId& extension_id) const {
   size_t allocated_rule_count = 0;
   extension_prefs_->GetDNRAllocatedGlobalRuleCount(extension_id,
                                                    &allocated_rule_count);
-  return (GetGlobalStaticRuleLimit() - allocated_global_rule_count_) +
-         allocated_rule_count;
+  return GetUnallocatedRuleCount() + allocated_rule_count;
 }
 
 void GlobalRulesTracker::ClearExtensionAllocation(
diff --git a/extensions/browser/api/declarative_net_request/global_rules_tracker.h b/extensions/browser/api/declarative_net_request/global_rules_tracker.h
index b3da193..0f7fe20 100644
--- a/extensions/browser/api/declarative_net_request/global_rules_tracker.h
+++ b/extensions/browser/api/declarative_net_request/global_rules_tracker.h
@@ -29,6 +29,9 @@
   bool OnExtensionRuleCountUpdated(const ExtensionId& extension_id,
                                    size_t new_rule_count);
 
+  // Returns the number of unallocated rules in the global pool.
+  size_t GetUnallocatedRuleCount() const;
+
   // Returns the number of rules in the global pool available for the extension
   // before the global limit is reached. This includes the extension's global
   // pool allocation.
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 60c1d10..b12bb2e 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1582,6 +1582,7 @@
   VIRTUALKEYBOARDPRIVATE_OPENSUGGESTIONSETTINGS = 1519,
   ACCESSIBILITY_PRIVATE_ENABLEPOINTSCAN = 1520,
   AUTOTESTPRIVATE_ACTIVATEADJACENTDESKSTOTARGETINDEX = 1521,
+  DECLARATIVENETREQUEST_GETAVAILABLESTATICRULECOUNT = 1522,
   // Last entry: Add new entries above, then run:
   // python tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json
index 04f111d..e501c02 100644
--- a/extensions/common/api/_api_features.json
+++ b/extensions/common/api/_api_features.json
@@ -162,6 +162,11 @@
     "dependencies": ["permission:declarativeNetRequest"],
     "contexts": ["blessed_extension"]
   },
+  "declarativeNetRequest.getAvailableStaticRuleCount": {
+    // TODO(crbug.com/983299): Enable on stable once the global rules limit
+    // feature is enabled by default.
+    "channel": "trunk"
+  },
   "declarativeNetRequest.onRuleMatchedDebug": {
     "dependencies": ["permission:declarativeNetRequest", "permission:declarativeNetRequestFeedback"],
     "location": "unpacked"
diff --git a/extensions/common/api/automation.idl b/extensions/common/api/automation.idl
index e23a7ac8..0374fcc3 100644
--- a/extensions/common/api/automation.idl
+++ b/extensions/common/api/automation.idl
@@ -33,7 +33,6 @@
     documentSelectionChanged,
     documentTitleChanged,
     dropeffectChanged,
-    editableTextChanged,
     enabledChanged,
     endOfTest,
     expanded,
diff --git a/extensions/common/api/declarative_net_request.idl b/extensions/common/api/declarative_net_request.idl
index b736b68..a04774b 100644
--- a/extensions/common/api/declarative_net_request.idl
+++ b/extensions/common/api/declarative_net_request.idl
@@ -440,6 +440,7 @@
   callback GetMatchedRulesCallback = void(RulesMatchedDetails details);
   callback GetEnabledRulesetsCallback = void(DOMString[] rulesetIds);
   callback IsRegexSupportedCallback = void(IsRegexSupportedResult result);
+  callback GetAvailableStaticRuleCountCallback = void(long count);
 
   interface Functions {
 
@@ -518,6 +519,11 @@
     // expression is supported and the reason if not.
     static void isRegexSupported(RegexOptions regexOptions,
                                  IsRegexSupportedCallback callback);
+
+    // Returns the number of static rules an extension can enable before the
+    // global static rule limit is reached.
+    // TODO(crbug.com/983299): Add documentation once implementation is complete.
+    [nodoc] static void getAvailableStaticRuleCount(GetAvailableStaticRuleCountCallback callback);
   };
 
   interface Properties {
diff --git a/extensions/renderer/api/automation/automation_api_util.cc b/extensions/renderer/api/automation/automation_api_util.cc
index f68ca03..e339fd28 100644
--- a/extensions/renderer/api/automation/automation_api_util.cc
+++ b/extensions/renderer/api/automation/automation_api_util.cc
@@ -118,7 +118,6 @@
     case ui::AXEventGenerator::Event::DOCUMENT_SELECTION_CHANGED:
     case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
     case ui::AXEventGenerator::Event::DROPEFFECT_CHANGED:
-    case ui::AXEventGenerator::Event::EDITABLE_TEXT_CHANGED:
     case ui::AXEventGenerator::Event::ENABLED_CHANGED:
     case ui::AXEventGenerator::Event::EXPANDED:
     case ui::AXEventGenerator::Event::FOCUS_CHANGED:
diff --git a/fuchsia/engine/browser/web_engine_content_browser_client.cc b/fuchsia/engine/browser/web_engine_content_browser_client.cc
index 840f23d..849c59f 100644
--- a/fuchsia/engine/browser/web_engine_content_browser_client.cc
+++ b/fuchsia/engine/browser/web_engine_content_browser_client.cc
@@ -26,7 +26,7 @@
 #include "fuchsia/engine/switches.h"
 #include "media/base/media_switches.h"
 #include "services/network/public/mojom/network_service.mojom.h"
-#include "third_party/blink/public/common/web_preferences/web_preferences.h"
+#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h"
 
 namespace {
 
@@ -119,7 +119,7 @@
   // Allow media to autoplay.
   // TODO(crbug.com/1067101): Provide a FIDL API to configure AutoplayPolicy.
   web_prefs->autoplay_policy =
-      blink::web_pref::AutoplayPolicy::kNoUserGestureRequired;
+      blink::mojom::AutoplayPolicy::kNoUserGestureRequired;
 }
 
 void WebEngineContentBrowserClient::RegisterBrowserInterfaceBindersForFrame(
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index 9e8b1a5..794a6d19 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -5575,7 +5575,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -5612,7 +5612,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -5649,7 +5649,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -6004,7 +6004,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -6809,7 +6809,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -6844,7 +6844,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -7441,7 +7441,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -8605,7 +8605,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -8772,7 +8772,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -9742,7 +9742,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -9778,7 +9778,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -10584,7 +10584,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -10621,7 +10621,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -11678,7 +11678,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -11880,7 +11880,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -11917,7 +11917,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -11954,7 +11954,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -11991,7 +11991,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12129,7 +12129,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12239,7 +12239,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12278,7 +12278,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12317,7 +12317,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12391,7 +12391,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12465,7 +12465,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12504,7 +12504,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12543,7 +12543,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12582,7 +12582,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12621,7 +12621,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12660,7 +12660,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12697,7 +12697,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12800,7 +12800,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12870,7 +12870,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12907,7 +12907,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12944,7 +12944,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -12980,7 +12980,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13016,7 +13016,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13053,7 +13053,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13090,7 +13090,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13127,7 +13127,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13197,7 +13197,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13267,7 +13267,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13304,7 +13304,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13341,7 +13341,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13378,7 +13378,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13448,7 +13448,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13485,7 +13485,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13555,7 +13555,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13690,7 +13690,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -13991,7 +13991,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14062,7 +14062,7 @@
       experimental: YES
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14100,7 +14100,7 @@
       experimental: YES
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14138,7 +14138,7 @@
       experimental: YES
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14303,7 +14303,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14339,7 +14339,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14437,7 +14437,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14474,7 +14474,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14541,7 +14541,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14578,7 +14578,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14615,7 +14615,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14652,7 +14652,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14689,7 +14689,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14726,7 +14726,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14763,7 +14763,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -14833,7 +14833,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -15062,7 +15062,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -15098,7 +15098,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -15133,7 +15133,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -15401,7 +15401,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -15438,7 +15438,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -15474,7 +15474,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -15574,7 +15574,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
@@ -15643,7 +15643,7 @@
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
         key: "chromium.resultdb.result_sink"
-        value: 0
+        value: 30
       }
       experiments {
         key: "luci.use_realms"
diff --git a/infra/config/generated/realms.cfg b/infra/config/generated/realms.cfg
index 3093a6e..149db88 100644
--- a/infra/config/generated/realms.cfg
+++ b/infra/config/generated/realms.cfg
@@ -71,6 +71,10 @@
     role: "role/buildbucket.triggerer"
     principals: "group:project-chromium-ci-schedulers"
   }
+  bindings {
+    role: "role/swarming.taskTriggerer"
+    principals: "user:chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+  }
 }
 realms {
   name: "codesearch"
@@ -137,6 +141,7 @@
     role: "role/swarming.poolUser"
     principals: "project:chromium-m86"
     principals: "project:chromium-m87"
+    principals: "user:chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
   }
 }
 realms {
diff --git a/infra/config/lib/ci.star b/infra/config/lib/ci.star
index a6a5ad1..5be49c0 100644
--- a/infra/config/lib/ci.star
+++ b/infra/config/lib/ci.star
@@ -693,7 +693,7 @@
         # TODO(crbug.com/1108016): Move this kwarg to ci.builder(), after
         # ResultSink and result_adapter is confirmed to work.
         experiments = {
-            "chromium.resultdb.result_sink": 0,
+            "chromium.resultdb.result_sink": 30,
         },
         **kwargs
     )
diff --git a/infra/config/swarming.star b/infra/config/swarming.star
index ca00e46..58ff96a8 100644
--- a/infra/config/swarming.star
+++ b/infra/config/swarming.star
@@ -61,6 +61,12 @@
     projects = [details.project for details in ACTIVE_MILESTONES.values()],
 )
 
+swarming.task_triggerers(
+    builder_realm = "ci",
+    pool_realm = "pools/ci",
+    users = ["chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"],
+)
+
 # Realm with bots that run try builds.
 #
 # The tasks here are also triggered via Buildbucket. See comment above.
diff --git a/ios/chrome/browser/translate/chrome_ios_translate_client.h b/ios/chrome/browser/translate/chrome_ios_translate_client.h
index 7d248b5..3e56c69 100644
--- a/ios/chrome/browser/translate/chrome_ios_translate_client.h
+++ b/ios/chrome/browser/translate/chrome_ios_translate_client.h
@@ -67,6 +67,7 @@
                        bool triggered_from_menu) override;
   bool IsTranslatableURL(const GURL& url) override;
   void ShowReportLanguageDetectionErrorUI(const GURL& report_url) override;
+  bool IsAutofillAssistantRunning() const override;
 
   id<LanguageSelectionHandler> language_selection_handler() {
     return language_selection_handler_;
diff --git a/ios/chrome/browser/translate/chrome_ios_translate_client.mm b/ios/chrome/browser/translate/chrome_ios_translate_client.mm
index d1419661..8ea8274 100644
--- a/ios/chrome/browser/translate/chrome_ios_translate_client.mm
+++ b/ios/chrome/browser/translate/chrome_ios_translate_client.mm
@@ -173,6 +173,10 @@
   return TranslateServiceIOS::IsTranslatableURL(url);
 }
 
+bool ChromeIOSTranslateClient::IsAutofillAssistantRunning() const {
+  return false;
+}
+
 void ChromeIOSTranslateClient::ShowReportLanguageDetectionErrorUI(
     const GURL& report_url) {
   NOTREACHED();
diff --git a/ios/web_view/internal/translate/web_view_translate_client.h b/ios/web_view/internal/translate/web_view_translate_client.h
index 79f70bab..dad02d2 100644
--- a/ios/web_view/internal/translate/web_view_translate_client.h
+++ b/ios/web_view/internal/translate/web_view_translate_client.h
@@ -75,6 +75,7 @@
                        bool triggered_from_menu) override;
   bool IsTranslatableURL(const GURL& url) override;
   void ShowReportLanguageDetectionErrorUI(const GURL& report_url) override;
+  bool IsAutofillAssistantRunning() const override;
 
  private:
   PrefService* pref_service_;
diff --git a/ios/web_view/internal/translate/web_view_translate_client.mm b/ios/web_view/internal/translate/web_view_translate_client.mm
index b635c9e..2c44446 100644
--- a/ios/web_view/internal/translate/web_view_translate_client.mm
+++ b/ios/web_view/internal/translate/web_view_translate_client.mm
@@ -131,6 +131,10 @@
   return !url.is_empty() && !url.SchemeIs(url::kFtpScheme);
 }
 
+bool WebViewTranslateClient::IsAutofillAssistantRunning() const {
+  return false;
+}
+
 void WebViewTranslateClient::ShowReportLanguageDetectionErrorUI(
     const GURL& report_url) {
   NOTREACHED();
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index 676eb651..d826c26 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -428,10 +428,14 @@
     public_deps += [ "//media/base/win:mf_cdm_proxy" ]
   }
 
-  if (is_chromecast || is_fuchsia) {
-    sources += [ "demuxer_memory_limit_low.cc" ]
-  } else if (is_android) {
+  # TODO(ziyangch): Check |is_chromecast| first when using cast media pipeline
+  # on Android cast devices.
+  if (is_android) {
     sources += [ "demuxer_memory_limit_android.cc" ]
+  } else if (is_chromecast) {
+    sources += [ "demuxer_memory_limit_cast.cc" ]
+  } else if (is_fuchsia) {
+    sources += [ "demuxer_memory_limit_low.cc" ]
   } else {
     sources += [ "demuxer_memory_limit_default.cc" ]
   }
@@ -633,6 +637,10 @@
       "mfplat.lib",
     ]
   }
+
+  if (is_chromecast && !is_android) {
+    sources += [ "demuxer_memory_limit_cast_unittest.cc" ]
+  }
 }
 
 source_set("perftests") {
diff --git a/media/base/demuxer.h b/media/base/demuxer.h
index a06793a..c9a4ebb 100644
--- a/media/base/demuxer.h
+++ b/media/base/demuxer.h
@@ -73,6 +73,12 @@
       base::OnceCallback<void(DemuxerStream::Type type,
                               const std::vector<DemuxerStream*>&)>;
 
+  enum DemuxerTypes {
+    kChunkDemuxer,
+    kFFmpegDemuxer,
+    kMediaUrlDemuxer,
+  };
+
   Demuxer();
   ~Demuxer() override;
 
diff --git a/media/base/demuxer_memory_limit.h b/media/base/demuxer_memory_limit.h
index 6fac9409..2492eca 100644
--- a/media/base/demuxer_memory_limit.h
+++ b/media/base/demuxer_memory_limit.h
@@ -8,17 +8,23 @@
 #include <stddef.h>
 
 #include "build/build_config.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/demuxer.h"
 #include "media/base/media_export.h"
+#include "media/base/video_decoder_config.h"
 
 namespace media {
 
 // The maximum amount of data (in bytes) a demuxer can keep in memory, for a
 // particular type of stream.
-MEDIA_EXPORT size_t GetDemuxerStreamAudioMemoryLimit();
-MEDIA_EXPORT size_t GetDemuxerStreamVideoMemoryLimit();
+MEDIA_EXPORT size_t
+GetDemuxerStreamAudioMemoryLimit(const AudioDecoderConfig* audio_config);
+MEDIA_EXPORT size_t
+GetDemuxerStreamVideoMemoryLimit(Demuxer::DemuxerTypes demuxer_type,
+                                 const VideoDecoderConfig* video_config);
 
 // The maximum amount of data (in bytes) a demuxer can keep in memory overall.
-MEDIA_EXPORT size_t GetDemuxerMemoryLimit();
+MEDIA_EXPORT size_t GetDemuxerMemoryLimit(Demuxer::DemuxerTypes demuxer_type);
 
 namespace internal {
 
@@ -26,13 +32,17 @@
 // above based on platform capabilities.
 
 // Default audio memory limit: 12MB (5 minutes of 320Kbps content).
+// Medium audio memory limit: 5MB.
 // Low audio memory limit: 2MB (1 minute of 256Kbps content).
 constexpr size_t kDemuxerStreamAudioMemoryLimitDefault = 12 * 1024 * 1024;
+constexpr size_t kDemuxerStreamAudioMemoryLimitMedium = 5 * 1024 * 1024;
 constexpr size_t kDemuxerStreamAudioMemoryLimitLow = 2 * 1024 * 1024;
 
 // Default video memory limit: 150MB (5 minutes of 4Mbps content).
+// Medium video memory limit: 80MB.
 // Low video memory limit: 30MB (1 minute of 4Mbps content).
 constexpr size_t kDemuxerStreamVideoMemoryLimitDefault = 150 * 1024 * 1024;
+constexpr size_t kDemuxerStreamVideoMemoryLimitMedium = 80 * 1024 * 1024;
 constexpr size_t kDemuxerStreamVideoMemoryLimitLow = 30 * 1024 * 1024;
 
 #if defined(OS_ANDROID)
diff --git a/media/base/demuxer_memory_limit_android.cc b/media/base/demuxer_memory_limit_android.cc
index b2f35ec..3ea8499 100644
--- a/media/base/demuxer_memory_limit_android.cc
+++ b/media/base/demuxer_memory_limit_android.cc
@@ -28,7 +28,8 @@
 
 }  // namespace
 
-size_t GetDemuxerStreamAudioMemoryLimit() {
+size_t GetDemuxerStreamAudioMemoryLimit(
+    const AudioDecoderConfig* /*audio_config*/) {
   static const size_t limit =
       SelectLimit(internal::kDemuxerStreamAudioMemoryLimitDefault,
                   internal::kDemuxerStreamAudioMemoryLimitLow,
@@ -36,7 +37,9 @@
   return limit;
 }
 
-size_t GetDemuxerStreamVideoMemoryLimit() {
+size_t GetDemuxerStreamVideoMemoryLimit(
+    Demuxer::DemuxerTypes /*demuxer_type*/,
+    const VideoDecoderConfig* /*video_config*/) {
   static const size_t limit =
       SelectLimit(internal::kDemuxerStreamVideoMemoryLimitDefault,
                   internal::kDemuxerStreamVideoMemoryLimitLow,
@@ -44,9 +47,9 @@
   return limit;
 }
 
-size_t GetDemuxerMemoryLimit() {
-  return GetDemuxerStreamAudioMemoryLimit() +
-         GetDemuxerStreamVideoMemoryLimit();
+size_t GetDemuxerMemoryLimit(Demuxer::DemuxerTypes demuxer_type) {
+  return GetDemuxerStreamAudioMemoryLimit(nullptr) +
+         GetDemuxerStreamVideoMemoryLimit(demuxer_type, nullptr);
 }
 
 }  // namespace media
diff --git a/media/base/demuxer_memory_limit_cast.cc b/media/base/demuxer_memory_limit_cast.cc
new file mode 100644
index 0000000..a4c2775
--- /dev/null
+++ b/media/base/demuxer_memory_limit_cast.cc
@@ -0,0 +1,62 @@
+// 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/base/demuxer_memory_limit.h"
+
+#include "base/check.h"
+#include "media/base/channel_layout.h"
+
+namespace media {
+
+size_t GetDemuxerStreamAudioMemoryLimit(
+    const AudioDecoderConfig* audio_config) {
+  if (!audio_config) {
+    return internal::kDemuxerStreamAudioMemoryLimitLow;
+  }
+
+  DCHECK(audio_config->IsValidConfig());
+  switch (audio_config->codec()) {
+    case kCodecEAC3:
+    case kCodecAC3:
+      return internal::kDemuxerStreamAudioMemoryLimitMedium;
+    case kCodecAAC:
+      if (ChannelLayoutToChannelCount(audio_config->channel_layout()) >= 5) {
+        return internal::kDemuxerStreamAudioMemoryLimitMedium;
+      }
+      return internal::kDemuxerStreamAudioMemoryLimitLow;
+    default:
+      return internal::kDemuxerStreamAudioMemoryLimitLow;
+  }
+}
+
+size_t GetDemuxerStreamVideoMemoryLimit(
+    Demuxer::DemuxerTypes demuxer_type,
+    const VideoDecoderConfig* video_config) {
+  switch (demuxer_type) {
+    case Demuxer::DemuxerTypes::kFFmpegDemuxer:
+      return internal::kDemuxerStreamVideoMemoryLimitDefault;
+    case Demuxer::DemuxerTypes::kChunkDemuxer:
+      if (!video_config) {
+        return internal::kDemuxerStreamVideoMemoryLimitLow;
+      }
+      DCHECK(video_config->IsValidConfig());
+      switch (video_config->codec()) {
+        case kCodecVP9:
+        case kCodecHEVC:
+        case kCodecDolbyVision:
+          return internal::kDemuxerStreamVideoMemoryLimitMedium;
+        default:
+          return internal::kDemuxerStreamVideoMemoryLimitLow;
+      }
+    case Demuxer::DemuxerTypes::kMediaUrlDemuxer:
+      return internal::kDemuxerStreamVideoMemoryLimitLow;
+  }
+}
+
+size_t GetDemuxerMemoryLimit(Demuxer::DemuxerTypes demuxer_type) {
+  return GetDemuxerStreamAudioMemoryLimit(nullptr) +
+         GetDemuxerStreamVideoMemoryLimit(demuxer_type, nullptr);
+}
+
+}  // namespace media
diff --git a/media/base/demuxer_memory_limit_cast_unittest.cc b/media/base/demuxer_memory_limit_cast_unittest.cc
new file mode 100644
index 0000000..41b68a2
--- /dev/null
+++ b/media/base/demuxer_memory_limit_cast_unittest.cc
@@ -0,0 +1,106 @@
+// 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 "base/optional.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/demuxer.h"
+#include "media/base/demuxer_memory_limit.h"
+#include "media/base/media_util.h"
+#include "media/base/video_decoder_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+static const gfx::Size kCodedSize(320, 240);
+static const gfx::Rect kVisibleRect(320, 240);
+static const gfx::Size kNaturalSize(320, 240);
+
+TEST(DemuxerMemoryLimitCastTest, GetDemuxerStreamAudioMemoryLimit) {
+  EXPECT_EQ(GetDemuxerStreamAudioMemoryLimit(nullptr),
+            internal::kDemuxerStreamAudioMemoryLimitLow);
+
+  AudioDecoderConfig audio_config_opus(
+      AudioCodec::kCodecOpus, SampleFormat::kSampleFormatS16,
+      ChannelLayout::CHANNEL_LAYOUT_STEREO, 5000 /* samples_per_second */,
+      EmptyExtraData(), EncryptionScheme::kUnencrypted);
+  EXPECT_EQ(GetDemuxerStreamAudioMemoryLimit(&audio_config_opus),
+            internal::kDemuxerStreamAudioMemoryLimitLow);
+
+  AudioDecoderConfig audio_config_ac3(
+      AudioCodec::kCodecAC3, SampleFormat::kSampleFormatS16,
+      ChannelLayout::CHANNEL_LAYOUT_STEREO, 5000 /* samples_per_second */,
+      EmptyExtraData(), EncryptionScheme::kUnencrypted);
+  EXPECT_EQ(GetDemuxerStreamAudioMemoryLimit(&audio_config_ac3),
+            internal::kDemuxerStreamAudioMemoryLimitMedium);
+
+  AudioDecoderConfig audio_config_aac_1(
+      AudioCodec::kCodecAAC, SampleFormat::kSampleFormatS16,
+      ChannelLayout::CHANNEL_LAYOUT_5_0, 5000 /* samples_per_second */,
+      EmptyExtraData(), EncryptionScheme::kUnencrypted);
+  EXPECT_EQ(GetDemuxerStreamAudioMemoryLimit(&audio_config_aac_1),
+            internal::kDemuxerStreamAudioMemoryLimitMedium);
+
+  AudioDecoderConfig audio_config_aac_2(
+      AudioCodec::kCodecAAC, SampleFormat::kSampleFormatS16,
+      ChannelLayout::CHANNEL_LAYOUT_STEREO, 5000 /* samples_per_second */,
+      EmptyExtraData(), EncryptionScheme::kUnencrypted);
+  EXPECT_EQ(GetDemuxerStreamAudioMemoryLimit(&audio_config_aac_2),
+            internal::kDemuxerStreamAudioMemoryLimitLow);
+}
+
+TEST(DemuxerMemoryLimitCastTest, GetDemuxerStreamVideoMemoryLimit) {
+  EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit(
+                Demuxer::DemuxerTypes::kFFmpegDemuxer, nullptr),
+            internal::kDemuxerStreamVideoMemoryLimitDefault);
+  EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit(
+                Demuxer::DemuxerTypes::kChunkDemuxer, nullptr),
+            internal::kDemuxerStreamVideoMemoryLimitLow);
+  EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit(
+                Demuxer::DemuxerTypes::kMediaUrlDemuxer, nullptr),
+            internal::kDemuxerStreamVideoMemoryLimitLow);
+
+  VideoDecoderConfig video_config(
+      kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN,
+      VideoDecoderConfig::AlphaMode::kIsOpaque, VideoColorSpace(),
+      kNoTransformation, kCodedSize, kVisibleRect, kNaturalSize,
+      EmptyExtraData(), EncryptionScheme::kUnencrypted);
+  EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit(
+                Demuxer::DemuxerTypes::kFFmpegDemuxer, &video_config),
+            internal::kDemuxerStreamVideoMemoryLimitDefault);
+  EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit(
+                Demuxer::DemuxerTypes::kChunkDemuxer, &video_config),
+            internal::kDemuxerStreamVideoMemoryLimitLow);
+  EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit(
+                Demuxer::DemuxerTypes::kMediaUrlDemuxer, &video_config),
+            internal::kDemuxerStreamVideoMemoryLimitLow);
+
+  video_config.Initialize(kCodecVP9, VIDEO_CODEC_PROFILE_UNKNOWN,
+                          VideoDecoderConfig::AlphaMode::kIsOpaque,
+                          VideoColorSpace(), kNoTransformation, kCodedSize,
+                          kVisibleRect, kNaturalSize, EmptyExtraData(),
+                          EncryptionScheme::kUnencrypted);
+  EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit(
+                Demuxer::DemuxerTypes::kFFmpegDemuxer, &video_config),
+            internal::kDemuxerStreamVideoMemoryLimitDefault);
+  EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit(
+                Demuxer::DemuxerTypes::kChunkDemuxer, &video_config),
+            internal::kDemuxerStreamVideoMemoryLimitMedium);
+  EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit(
+                Demuxer::DemuxerTypes::kMediaUrlDemuxer, &video_config),
+            internal::kDemuxerStreamVideoMemoryLimitLow);
+}
+
+TEST(DemuxerMemoryLimitCastTest, GetDemuxerMemoryLimit) {
+  EXPECT_EQ(GetDemuxerMemoryLimit(Demuxer::DemuxerTypes::kFFmpegDemuxer),
+            internal::kDemuxerStreamAudioMemoryLimitLow +
+                internal::kDemuxerStreamVideoMemoryLimitDefault);
+  EXPECT_EQ(GetDemuxerMemoryLimit(Demuxer::DemuxerTypes::kChunkDemuxer),
+            internal::kDemuxerStreamAudioMemoryLimitLow +
+                internal::kDemuxerStreamVideoMemoryLimitLow);
+  EXPECT_EQ(GetDemuxerMemoryLimit(Demuxer::DemuxerTypes::kMediaUrlDemuxer),
+            internal::kDemuxerStreamAudioMemoryLimitLow +
+                internal::kDemuxerStreamVideoMemoryLimitLow);
+}
+
+}  // namespace media
diff --git a/media/base/demuxer_memory_limit_default.cc b/media/base/demuxer_memory_limit_default.cc
index 4fb4551e..896d534 100644
--- a/media/base/demuxer_memory_limit_default.cc
+++ b/media/base/demuxer_memory_limit_default.cc
@@ -6,17 +6,20 @@
 
 namespace media {
 
-size_t GetDemuxerStreamAudioMemoryLimit() {
+size_t GetDemuxerStreamAudioMemoryLimit(
+    const AudioDecoderConfig* /*audio_config*/) {
   return internal::kDemuxerStreamAudioMemoryLimitDefault;
 }
 
-size_t GetDemuxerStreamVideoMemoryLimit() {
+size_t GetDemuxerStreamVideoMemoryLimit(
+    Demuxer::DemuxerTypes /*demuxer_type*/,
+    const VideoDecoderConfig* /*video_config*/) {
   return internal::kDemuxerStreamVideoMemoryLimitDefault;
 }
 
-size_t GetDemuxerMemoryLimit() {
-  return GetDemuxerStreamAudioMemoryLimit() +
-         GetDemuxerStreamVideoMemoryLimit();
+size_t GetDemuxerMemoryLimit(Demuxer::DemuxerTypes demuxer_type) {
+  return GetDemuxerStreamAudioMemoryLimit(nullptr) +
+         GetDemuxerStreamVideoMemoryLimit(demuxer_type, nullptr);
 }
 
 }  // namespace media
diff --git a/media/base/demuxer_memory_limit_low.cc b/media/base/demuxer_memory_limit_low.cc
index 054fafe..71dc442 100644
--- a/media/base/demuxer_memory_limit_low.cc
+++ b/media/base/demuxer_memory_limit_low.cc
@@ -8,17 +8,20 @@
 
 namespace media {
 
-size_t GetDemuxerStreamAudioMemoryLimit() {
+size_t GetDemuxerStreamAudioMemoryLimit(
+    const AudioDecoderConfig* /*audio_config*/) {
   return internal::kDemuxerStreamAudioMemoryLimitLow;
 }
 
-size_t GetDemuxerStreamVideoMemoryLimit() {
+size_t GetDemuxerStreamVideoMemoryLimit(
+    Demuxer::DemuxerTypes /*demuxer_type*/,
+    const VideoDecoderConfig* /*video_config*/) {
   return internal::kDemuxerStreamVideoMemoryLimitLow;
 }
 
-size_t GetDemuxerMemoryLimit() {
-  return GetDemuxerStreamAudioMemoryLimit() +
-         GetDemuxerStreamVideoMemoryLimit();
+size_t GetDemuxerMemoryLimit(Demuxer::DemuxerTypes demuxer_type) {
+  return GetDemuxerStreamAudioMemoryLimit(nullptr) +
+         GetDemuxerStreamVideoMemoryLimit(demuxer_type, nullptr);
 }
 
 }  // namespace media
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc
index e889678..f68741e 100644
--- a/media/base/video_frame.cc
+++ b/media/base/video_frame.cc
@@ -1102,12 +1102,9 @@
 bool VideoFrame::HasTextures() const {
   // A SharedImage can be turned into a texture, and so it counts as a texture
   // in the context of this call.
-  if (mailbox_holders_[0].mailbox.IsSharedImage())
-    return true;
-
-  DCHECK(!wrapped_frame_ || !wrapped_frame_->HasTextures());
   return wrapped_frame_ ? wrapped_frame_->HasTextures()
-                        : !mailbox_holders_[0].mailbox.IsZero();
+                        : (mailbox_holders_[0].mailbox.IsSharedImage() ||
+                           !mailbox_holders_[0].mailbox.IsZero());
 }
 
 size_t VideoFrame::NumTextures() const {
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index d34db63..391c9e2e 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -1858,7 +1858,8 @@
 bool FFmpegDemuxer::IsMaxMemoryUsageReached() const {
   DCHECK(task_runner_->BelongsToCurrentThread());
 
-  size_t memory_left = GetDemuxerMemoryLimit();
+  size_t memory_left =
+      GetDemuxerMemoryLimit(Demuxer::DemuxerTypes::kFFmpegDemuxer);
   for (const auto& stream : streams_) {
     if (!stream)
       continue;
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc
index 53a9012..488f9e2 100644
--- a/media/filters/source_buffer_stream.cc
+++ b/media/filters/source_buffer_stream.cc
@@ -165,9 +165,10 @@
       highest_output_buffer_timestamp_(kNoTimestamp),
       max_interbuffer_distance_(
           base::TimeDelta::FromMilliseconds(kMinimumInterbufferDistanceInMs)),
-      memory_limit_(GetDemuxerStreamAudioMemoryLimit()) {
+      memory_limit_(GetDemuxerStreamAudioMemoryLimit(&audio_config)) {
   DCHECK(audio_config.IsValidConfig());
   audio_configs_.push_back(audio_config);
+  DVLOG(2) << __func__ << ": audio_buffer_size= " << memory_limit_;
 }
 
 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
@@ -179,9 +180,12 @@
       highest_output_buffer_timestamp_(kNoTimestamp),
       max_interbuffer_distance_(
           base::TimeDelta::FromMilliseconds(kMinimumInterbufferDistanceInMs)),
-      memory_limit_(GetDemuxerStreamVideoMemoryLimit()) {
+      memory_limit_(
+          GetDemuxerStreamVideoMemoryLimit(Demuxer::DemuxerTypes::kChunkDemuxer,
+                                           &video_config)) {
   DCHECK(video_config.IsValidConfig());
   video_configs_.push_back(video_config);
+  DVLOG(2) << __func__ << ": video_buffer_size= " << memory_limit_;
 }
 
 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config,
@@ -194,7 +198,8 @@
       highest_output_buffer_timestamp_(kNoTimestamp),
       max_interbuffer_distance_(
           base::TimeDelta::FromMilliseconds(kMinimumInterbufferDistanceInMs)),
-      memory_limit_(GetDemuxerStreamAudioMemoryLimit()) {}
+      memory_limit_(
+          GetDemuxerStreamAudioMemoryLimit(nullptr /*audio_config*/)) {}
 
 SourceBufferStream::~SourceBufferStream() = default;
 
diff --git a/media/filters/source_buffer_stream.h b/media/filters/source_buffer_stream.h
index fa70e48..718ae0c 100644
--- a/media/filters/source_buffer_stream.h
+++ b/media/filters/source_buffer_stream.h
@@ -484,6 +484,11 @@
       base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
 
   // The maximum amount of data in bytes the stream will keep in memory.
+  // |memory_limit_| is initialized based on the audio/video configuration in
+  // the constructor, but either user-setting of |memory_limit_| or
+  // memory-pressure-based adjustment to determine effective limit in the
+  // eviction heuristic can cause the result to vary from the value set in
+  // constructor.
   size_t memory_limit_;
 
   // Indicates that a kConfigChanged status has been reported by GetNextBuffer()
diff --git a/media/formats/mp4/track_run_iterator.cc b/media/formats/mp4/track_run_iterator.cc
index e8205d05..c909c4a 100644
--- a/media/formats/mp4/track_run_iterator.cc
+++ b/media/formats/mp4/track_run_iterator.cc
@@ -15,6 +15,7 @@
 #include "base/stl_util.h"
 #include "build/chromecast_buildflags.h"
 #include "media/base/decrypt_config.h"
+#include "media/base/demuxer.h"
 #include "media/base/demuxer_memory_limit.h"
 #include "media/base/encryption_pattern.h"
 #include "media/base/encryption_scheme.h"
@@ -424,7 +425,8 @@
 
       // Avoid allocating insane sample counts for invalid media.
       const size_t max_sample_count =
-          GetDemuxerMemoryLimit() / sizeof(decltype(tri.samples)::value_type);
+          GetDemuxerMemoryLimit(Demuxer::DemuxerTypes::kChunkDemuxer) /
+          sizeof(decltype(tri.samples)::value_type);
       RCHECK_MEDIA_LOGGED(
           base::strict_cast<size_t>(trun.sample_count) <= max_sample_count,
           media_log_, "Metadata overhead exceeds storage limit.");
diff --git a/media/fuchsia/media_unittests.cmx b/media/fuchsia/media_unittests.cmx
index f0f21e2..923550a6 100644
--- a/media/fuchsia/media_unittests.cmx
+++ b/media/fuchsia/media_unittests.cmx
@@ -3,11 +3,11 @@
     "fuchsia.test": {
       "injected-services": {
         "fuchsia.intl.PropertyProvider": "fuchsia-pkg://fuchsia.com/intl_property_manager#meta/intl_property_manager.cmx",
-        "fuchsia.media.Audio": "fuchsia-pkg://fuchsia.com/audio#meta/audio.cmx",
         "fuchsia.mediacodec.CodecFactory": "fuchsia-pkg://fuchsia.com/codec_factory#meta/codec_factory.cmx"
       },
       "system-services": [
         "fuchsia.sysmem.Allocator",
+        "fuchsia.media.Audio",
         "fuchsia.media.AudioCore"
       ]
     }
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index 3ad1c21..59c5e41 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -16,6 +16,7 @@
 
   flags = [
     "USE_VAAPI=$use_vaapi",
+    "USE_VAAPI_IMAGE_CODECS=$use_vaapi_image_codecs",
     "USE_V4L2_CODEC=$use_v4l2_codec",
     "USE_LIBV4L2=$use_v4lplugin",
   ]
diff --git a/media/gpu/args.gni b/media/gpu/args.gni
index bf656a5..8432ec2 100644
--- a/media/gpu/args.gni
+++ b/media/gpu/args.gni
@@ -23,3 +23,11 @@
   # encrypted content with HW video decoders.
   use_chromeos_protected_media = false
 }
+
+# GN requires args that depend on other args to be declared in successive
+# declare_args() blocks.
+declare_args() {
+  # VA-API also allows decoding of images, but we don't want to use this
+  # outside of chromeos, even if video decoding is enabled.
+  use_vaapi_image_codecs = use_vaapi && is_chromeos
+}
diff --git a/media/gpu/chromeos/fourcc.h b/media/gpu/chromeos/fourcc.h
index 652f203..f9e5d691 100644
--- a/media/gpu/chromeos/fourcc.h
+++ b/media/gpu/chromeos/fourcc.h
@@ -31,7 +31,7 @@
  public:
   enum Value : uint32_t {
     // RGB formats.
-    // https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/pixfmt-rgb.html
+    // https://linuxtv.org/downloads/v4l-dvb-apis-new/userspace-api/v4l/pixfmt-rgb.html
     // Maps to PIXEL_FORMAT_ARGB, V4L2_PIX_FMT_ABGR32, VA_FOURCC_BGRA.
     // 32bpp BGRA (byte-order), 1 plane.
     AR24 = ComposeFourcc('A', 'R', '2', '4'),
@@ -56,7 +56,7 @@
     RGB4 = ComposeFourcc('R', 'G', 'B', '4'),
 
     // YUV420 single-planar formats.
-    // https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/pixfmt-yuv420.html
+    // https://linuxtv.org/downloads/v4l-dvb-apis-new/userspace-api/v4l/pixfmt-yuv420.html
     // Maps to PIXEL_FORMAT_I420, V4L2_PIX_FMT_YUV420, VA_FOURCC_I420.
     // 12bpp YUV planar 1x1 Y, 2x2 UV samples.
     YU12 = ComposeFourcc('Y', 'U', '1', '2'),
@@ -65,20 +65,20 @@
     YV12 = ComposeFourcc('Y', 'V', '1', '2'),
 
     // YUV420 multi-planar format.
-    // https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/pixfmt-yuv420m.htm
+    // https://linuxtv.org/downloads/v4l-dvb-apis-new/userspace-api/v4l/pixfmt-yuv420m.html
     // Maps to PIXEL_FORMAT_I420, V4L2_PIX_FMT_YUV420M.
     YM12 = ComposeFourcc('Y', 'M', '1', '2'),
     // Maps to PIXEL_FORMAT_YV12, V4L2_PIX_FMT_YVU420M.
     YM21 = ComposeFourcc('Y', 'M', '2', '1'),
 
     // YUYV format.
-    // https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/pixfmt-yuyv.html
+    // https://linuxtv.org/downloads/v4l-dvb-apis-new/userspace-api/v4l/pixfmt-yuyv.html
     // Maps to PIXEL_FORMAT_YUY2, V4L2_PIX_FMT_YUYV, VA_FOURCC_YUY2.
     // 16bpp YUV planar (YUV 4:2:2), YUYV (byte-order), 1 plane.
     YUYV = ComposeFourcc('Y', 'U', 'Y', 'V'),
 
     // NV12 single-planar format.
-    // https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/pixfmt-nv12.html
+    // https://linuxtv.org/downloads/v4l-dvb-apis-new/userspace-api/v4l/pixfmt-nv12.html
     // Maps to PIXEL_FORMAT_NV12, V4L2_PIX_FMT_NV12, VA_FOURCC_NV12.
     // 12bpp with Y plane followed by a 2x2 interleaved UV plane.
     NV12 = ComposeFourcc('N', 'V', '1', '2'),
@@ -87,20 +87,20 @@
     NV21 = ComposeFourcc('N', 'V', '2', '1'),
 
     // NV12 multi-planar format.
-    // https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/pixfmt-nv12m.html
+    // https://linuxtv.org/downloads/v4l-dvb-apis-new/userspace-api/v4l/pixfmt-nv12m.html
     // Maps to PIXEL_FORMAT_NV12, V4L2_PIX_FMT_NV12M,
     NM12 = ComposeFourcc('N', 'M', '1', '2'),
     // Maps to PIXEL_FORMAT_NV21, V4L2_PIX_FMT_NV21M.
     NM21 = ComposeFourcc('N', 'M', '2', '1'),
 
     // YUV422 multi-planar format.
-    // https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/pixfmt-yuv422m.html
+    // https://linuxtv.org/downloads/v4l-dvb-apis-new/userspace-api/v4l/pixfmt-yuv422m.html
     // Maps to PIXEL_FORMAT_I422, V4L2_PIX_FMT_YUV422M
     // 16bpp YUV planar 1x1 Y, 2x1 UV samples.
     YM16 = ComposeFourcc('Y', 'M', '1', '6'),
 
     // V4L2 proprietary format.
-    // https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/pixfmt-reserved.html
+    // https://linuxtv.org/downloads/v4l-dvb-apis-new/userspace-api/v4l/pixfmt-reserved.html
     // Maps to V4L2_PIX_FMT_MT21C.
     // It is used for MT8173 hardware video decoder output and should be
     // converted by MT8173 image processor for compositor to render.
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h
index 0a2170a..ba535e6 100644
--- a/net/quic/quic_flags_list.h
+++ b/net/quic/quic_flags_list.h
@@ -228,7 +228,7 @@
 QUIC_FLAG(bool, FLAGS_quic_enable_http3_grease_randomness, true)
 
 // If true, disable QUIC version h3-27.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_draft_27, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_draft_27, true)
 
 // If true, server push will be allowed in QUIC versions using HTTP/3.
 QUIC_FLAG(bool, FLAGS_quic_enable_http3_server_push, false)
@@ -282,12 +282,6 @@
           FLAGS_quic_reloadable_flag_quic_disable_server_blackhole_detection,
           false)
 
-// When true, QUIC+TLS versions will send the key_update_not_yet_supported
-// transport parameter.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_send_key_update_not_yet_supported,
-          true)
-
 // If true, QUIC will default enable MTU discovery, with a target of 1450 bytes.
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_enable_mtu_discovery_at_server,
@@ -338,7 +332,7 @@
 // GOAWAY frame.
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_fix_http3_goaway_stream_id,
-          false)
+          true)
 
 // If true, close connection if writer is still blocked when OnCanWrite is
 // called.
@@ -387,7 +381,7 @@
 // If true, abort async QPACK header decompression in QuicSpdyStream::OnClose().
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_abort_qpack_on_stream_close,
-          false)
+          true)
 
 // If true, do not arm PTO for application data until handshake confirmed.
 QUIC_FLAG(bool,
@@ -413,7 +407,7 @@
 QUIC_FLAG(
     bool,
     FLAGS_quic_reloadable_flag_quic_bbr2_use_post_inflight_to_detect_queuing,
-    false)
+    true)
 
 // If true, QUIC BBRv2 will use 15% inflight_hi headroom, which is the default
 // for TCP.
@@ -436,7 +430,7 @@
 // sent.
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_deallocate_message_right_after_sent,
-          false)
+          true)
 
 // If true, drop initial keys at the end of writing and unify the fixes for
 // missing initial keys.
@@ -468,3 +462,15 @@
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_let_connection_handle_pings,
           true)
+
+// If true, BBRv2 will 1) change the default STARTUP and DRAIN cwnd gain to 2.0,
+// and 2) change the meaning of connection option BBQ2 to use 2.885 for STARTUP
+// and DRAIN cwnd gain.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr2_flip_bbq2, true)
+
+// If true, use http2::HuffmanEncodeFast() instead of HuffmanEncode() and
+// eliminate one string copy for QPACK encoding used in IETF QUIC.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_fast_huffman_encoder, false)
+
+// When true, QUIC+TLS versions will support key updates.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_key_update_supported, false)
diff --git a/net/quic/quic_test_packet_printer.cc b/net/quic/quic_test_packet_printer.cc
index 86edab08..46e79d6 100644
--- a/net/quic/quic_test_packet_printer.cc
+++ b/net/quic/quic_test_packet_printer.cc
@@ -164,6 +164,19 @@
     *output_ << "OnStreamsBlockedFrame: " << frame;
     return true;
   }
+  void OnKeyUpdate() override { *output_ << "OnKeyUpdate\n"; }
+  void OnDecryptedFirstPacketInKeyPhase() override {
+    *output_ << "OnDecryptedFirstPacketInKeyPhase\n";
+  }
+  std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter()
+      override {
+    *output_ << "AdvanceKeysAndCreateCurrentOneRttDecrypter\n";
+    return nullptr;
+  }
+  std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override {
+    *output_ << "CreateCurrentOneRttEncrypter\n";
+    return nullptr;
+  }
   bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override {
     *output_ << "OnWindowUpdateFrame: " << frame;
     return true;
diff --git a/net/spdy/platform/impl/spdy_flags_impl.cc b/net/spdy/platform/impl/spdy_flags_impl.cc
index abb4a9a..ca291c6 100644
--- a/net/spdy/platform/impl/spdy_flags_impl.cc
+++ b/net/spdy/platform/impl/spdy_flags_impl.cc
@@ -4,8 +4,10 @@
 
 #include "net/spdy/platform/impl/spdy_flags_impl.h"
 
-// If true, use indexed name if possible when sending
-// Literal Header Field without Indexing instruction.
-bool spdy_hpack_use_indexed_name = true;
+// If true, use http2::HuffmanSize() instead of
+// spdy::HpackHuffmanTable::EncodedSize() and http2::HuffmanEncodeFast()
+// instead of spdy::HpackHuffmanTable::EncodeString() for HPACK encoding used
+// in HTTP/2 and Google QUIC (not IETF QUIC).
+bool http2_use_fast_huffman_encoder = true;
 
 namespace spdy {}  // namespace spdy
diff --git a/net/spdy/platform/impl/spdy_flags_impl.h b/net/spdy/platform/impl/spdy_flags_impl.h
index ae3f74e..ddfd969 100644
--- a/net/spdy/platform/impl/spdy_flags_impl.h
+++ b/net/spdy/platform/impl/spdy_flags_impl.h
@@ -7,7 +7,7 @@
 
 #include "net/base/net_export.h"
 
-NET_EXPORT_PRIVATE extern bool spdy_hpack_use_indexed_name;
+NET_EXPORT_PRIVATE extern bool http2_use_fast_huffman_encoder;
 
 inline bool GetSpdyReloadableFlagImpl(bool flag) {
   return flag;
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc
index fb68ee68..a7f48a5 100644
--- a/pdf/out_of_process_instance.cc
+++ b/pdf/out_of_process_instance.cc
@@ -1852,8 +1852,8 @@
 void OutOfProcessInstance::HandleUpdateScrollMessage(
     const pp::VarDictionary& dict) {
   if (!base::FeatureList::IsEnabled(features::kPDFViewerUpdate) ||
-      !dict.Get(pp::Var(kJSUpdateScrollX)).is_int() ||
-      !dict.Get(pp::Var(kJSUpdateScrollY)).is_int()) {
+      !dict.Get(pp::Var(kJSUpdateScrollX)).is_number() ||
+      !dict.Get(pp::Var(kJSUpdateScrollY)).is_number()) {
     NOTREACHED();
     return;
   }
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc
index fe604df..70fa4cb5 100644
--- a/services/network/public/cpp/features.cc
+++ b/services/network/public/cpp/features.cc
@@ -177,11 +177,7 @@
 // See also https://crbug.com/920634
 const base::Feature kRequestInitiatorSiteLockEnfocement = {
     "RequestInitiatorSiteLockEnfocement",
-#if defined(OS_ANDROID)
-    base::FEATURE_DISABLED_BY_DEFAULT};
-#else
     base::FEATURE_ENABLED_BY_DEFAULT};
-#endif
 
 // When the CertVerifierService is enabled, certificate verification will not be
 // performed in the network service, but will instead be brokered to a separate
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 46933d9..2fb705a 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -41167,6 +41167,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41209,6 +41212,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41251,6 +41257,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41293,6 +41302,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41335,6 +41347,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41377,6 +41392,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41419,6 +41437,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41461,6 +41482,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41503,6 +41527,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41545,6 +41572,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41587,6 +41617,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41629,6 +41662,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41671,6 +41707,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41713,6 +41752,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41755,6 +41797,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41797,6 +41842,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41839,6 +41887,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41881,6 +41932,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41942,6 +41996,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -41981,6 +42038,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42020,6 +42080,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42059,6 +42122,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42098,6 +42164,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42137,6 +42206,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42176,6 +42248,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42215,6 +42290,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42254,6 +42332,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42293,6 +42374,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42332,6 +42416,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42371,6 +42458,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42410,6 +42500,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42449,6 +42542,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42488,6 +42584,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42527,6 +42626,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42566,6 +42668,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -42605,6 +42710,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6S 12.3.1",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 9de8711..a4a98354 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -19214,6 +19214,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19256,6 +19259,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19298,6 +19304,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19340,6 +19349,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19382,6 +19394,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19424,6 +19439,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19466,6 +19484,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19508,6 +19529,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19550,6 +19574,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19592,6 +19619,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19634,6 +19664,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19676,6 +19709,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19718,6 +19754,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19760,6 +19799,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19802,6 +19844,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19844,6 +19889,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19886,6 +19934,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19928,6 +19979,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19970,6 +20024,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20012,6 +20069,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20054,6 +20114,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20096,6 +20159,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20138,6 +20204,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20180,6 +20249,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20222,6 +20294,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20264,6 +20339,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20306,6 +20384,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20348,6 +20429,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20390,6 +20474,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20432,6 +20519,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20474,6 +20564,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20516,6 +20609,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20558,6 +20654,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20600,6 +20699,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20642,6 +20744,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20684,6 +20789,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20726,6 +20834,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20768,6 +20879,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20810,6 +20924,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20852,6 +20969,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20894,6 +21014,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20936,6 +21059,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20978,6 +21104,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21020,6 +21149,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21062,6 +21194,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21104,6 +21239,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21153,6 +21291,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21198,6 +21339,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21243,6 +21387,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21288,6 +21435,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21333,6 +21483,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21378,6 +21531,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21423,6 +21579,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21468,6 +21627,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21513,6 +21675,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21558,6 +21723,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21603,6 +21771,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21648,6 +21819,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21693,6 +21867,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21738,6 +21915,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21783,6 +21963,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21828,6 +22011,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21873,6 +22059,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21918,6 +22107,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21963,6 +22155,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22008,6 +22203,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22053,6 +22251,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22098,6 +22299,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22144,6 +22348,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22190,6 +22397,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22236,6 +22446,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22282,6 +22495,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22328,6 +22544,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22374,6 +22593,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22421,6 +22643,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22468,6 +22693,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22515,6 +22743,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22562,6 +22793,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22609,6 +22843,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22656,6 +22893,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22703,6 +22943,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22750,6 +22993,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22797,6 +23043,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22844,6 +23093,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22890,6 +23142,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22936,6 +23191,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22982,6 +23240,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23028,6 +23289,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23074,6 +23338,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23120,6 +23387,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23166,6 +23436,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23212,6 +23485,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23258,6 +23534,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23304,6 +23583,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23351,6 +23633,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23398,6 +23683,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23445,6 +23733,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23492,6 +23783,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23538,6 +23832,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23583,6 +23880,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23628,6 +23928,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23673,6 +23976,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23719,6 +24025,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23765,6 +24074,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23811,6 +24123,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23857,6 +24172,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23903,6 +24221,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23948,6 +24269,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23993,6 +24317,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24038,6 +24365,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24083,6 +24413,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24128,6 +24461,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24173,6 +24509,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24219,6 +24558,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24265,6 +24607,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24311,6 +24656,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24357,6 +24705,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24403,6 +24754,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24448,6 +24802,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24493,6 +24850,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24538,6 +24898,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24583,6 +24946,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24628,6 +24994,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24673,6 +25042,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24719,6 +25091,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24765,6 +25140,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24811,6 +25189,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24857,6 +25238,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24903,6 +25287,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24948,6 +25335,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24993,6 +25383,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25038,6 +25431,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25083,6 +25479,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25128,6 +25527,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25173,6 +25575,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25218,6 +25623,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25263,6 +25671,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25308,6 +25719,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25353,6 +25767,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25398,6 +25815,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25443,6 +25863,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25488,6 +25911,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25533,6 +25959,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25578,6 +26007,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25623,6 +26055,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25668,6 +26103,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25713,6 +26151,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25758,6 +26199,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25803,6 +26247,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25848,6 +26295,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25893,6 +26343,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25938,6 +26391,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -25983,6 +26439,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26028,6 +26487,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26073,6 +26535,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26118,6 +26583,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26163,6 +26631,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26209,6 +26680,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "cronet_test_iPhone X 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26251,6 +26725,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "cronet_test_iPhone X 13.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26297,6 +26774,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26339,6 +26819,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26381,6 +26864,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26423,6 +26909,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26465,6 +26954,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26507,6 +26999,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26549,6 +27044,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26591,6 +27089,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26634,6 +27135,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26677,6 +27181,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26721,6 +27228,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26765,6 +27275,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26808,6 +27321,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26851,6 +27367,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26894,6 +27413,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26937,6 +27459,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -26979,6 +27504,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27021,6 +27549,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27063,6 +27594,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27106,6 +27640,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27148,6 +27685,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27190,6 +27730,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27233,6 +27776,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27275,6 +27821,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27317,6 +27866,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27359,6 +27911,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27401,6 +27956,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27443,6 +28001,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27485,6 +28046,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27527,6 +28091,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27569,6 +28136,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27611,6 +28181,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27659,6 +28232,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27703,6 +28279,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27747,6 +28326,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27791,6 +28373,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27835,6 +28420,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27879,6 +28467,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27923,6 +28514,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -27967,6 +28561,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28011,6 +28608,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28055,6 +28655,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28099,6 +28702,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28143,6 +28749,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28187,6 +28796,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28231,6 +28843,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28275,6 +28890,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28319,6 +28937,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28364,6 +28985,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28409,6 +29033,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28454,6 +29081,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28500,6 +29130,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28546,6 +29179,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28592,6 +29228,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28638,6 +29277,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28683,6 +29325,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28728,6 +29373,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28773,6 +29421,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28818,6 +29469,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28864,6 +29518,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28909,6 +29566,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28953,6 +29613,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -28998,6 +29661,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29043,6 +29709,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29087,6 +29756,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29131,6 +29803,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29175,6 +29850,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29219,6 +29897,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29263,6 +29944,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29307,6 +29991,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29352,6 +30039,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29397,6 +30087,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29441,6 +30134,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29485,6 +30181,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29529,6 +30228,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29573,6 +30275,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29618,6 +30323,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29663,6 +30371,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29707,6 +30418,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29751,6 +30465,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29795,6 +30512,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29839,6 +30559,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29883,6 +30606,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29927,6 +30653,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -29971,6 +30700,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30015,6 +30747,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30059,6 +30794,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30103,6 +30841,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30147,6 +30888,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30191,6 +30935,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30235,6 +30982,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30279,6 +31029,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30323,6 +31076,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30367,6 +31123,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30411,6 +31170,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPad Air 2 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30455,6 +31217,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone X 13.5",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30519,6 +31284,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30561,6 +31329,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30603,6 +31374,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30645,6 +31419,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30687,6 +31464,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30729,6 +31509,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30771,6 +31554,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30813,6 +31599,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30855,6 +31644,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30897,6 +31689,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30939,6 +31734,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -30981,6 +31779,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31023,6 +31824,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31065,6 +31869,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31108,6 +31915,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad (6th generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31151,6 +31961,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air (3rd generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31194,6 +32007,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31237,6 +32053,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31280,6 +32099,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad (6th generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31324,6 +32146,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31368,6 +32193,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31412,6 +32240,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31456,6 +32287,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad (6th generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31500,6 +32334,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air (3rd generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31544,6 +32381,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31588,6 +32428,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31632,6 +32475,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad (6th generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31675,6 +32521,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31718,6 +32567,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31761,6 +32613,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31804,6 +32659,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad (6th generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31847,6 +32705,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air (3rd generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31890,6 +32751,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31933,6 +32797,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -31976,6 +32843,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad (6th generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32020,6 +32890,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32064,6 +32937,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32108,6 +32984,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32151,6 +33030,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32193,6 +33075,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32235,6 +33120,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32278,6 +33166,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad (6th generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32321,6 +33212,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air (3rd generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32364,6 +33258,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32407,6 +33304,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32449,6 +33349,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32491,6 +33394,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32533,6 +33439,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32576,6 +33485,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad (6th generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32619,6 +33531,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air (3rd generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32662,6 +33577,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32705,6 +33623,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32747,6 +33668,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32789,6 +33713,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32831,6 +33758,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32873,6 +33803,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32916,6 +33849,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad (6th generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -32959,6 +33895,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33002,6 +33941,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33045,6 +33987,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33087,6 +34032,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33129,6 +34077,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33171,6 +34122,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33213,6 +34167,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33255,6 +34212,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33297,6 +34257,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33339,6 +34302,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33381,6 +34347,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33423,6 +34392,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33465,6 +34437,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33507,6 +34482,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33549,6 +34527,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33591,6 +34572,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33633,6 +34617,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33675,6 +34662,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33717,6 +34707,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33759,6 +34752,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33801,6 +34797,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33843,6 +34842,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33892,6 +34894,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33934,6 +34939,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -33976,6 +34984,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34018,6 +35029,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34060,6 +35074,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34102,6 +35119,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34144,6 +35164,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34186,6 +35209,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34228,6 +35254,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34270,6 +35299,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34312,6 +35344,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34355,6 +35390,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34398,6 +35436,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34441,6 +35482,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34484,6 +35528,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34528,6 +35575,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34572,6 +35622,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34616,6 +35669,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34660,6 +35716,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34704,6 +35763,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34748,6 +35810,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34791,6 +35856,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34834,6 +35902,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34877,6 +35948,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34920,6 +35994,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -34963,6 +36040,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35006,6 +36086,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35050,6 +36133,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35094,6 +36180,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35137,6 +36226,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35179,6 +36271,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35222,6 +36317,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35265,6 +36363,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35308,6 +36409,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35350,6 +36454,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35392,6 +36499,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35434,6 +36544,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35477,6 +36590,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35520,6 +36636,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone 7 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35563,6 +36682,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35605,6 +36727,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35647,6 +36772,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35689,6 +36817,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35732,6 +36863,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35775,6 +36909,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35818,6 +36955,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone X 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35860,6 +37000,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35902,6 +37045,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35944,6 +37090,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -35986,6 +37135,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36028,6 +37180,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36070,6 +37225,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36112,6 +37270,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36154,6 +37315,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36196,6 +37360,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36238,6 +37405,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36280,6 +37450,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36322,6 +37495,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36364,6 +37540,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s Plus 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -36406,6 +37585,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 14.2",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 5ffd4d9..034d323 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -14226,6 +14226,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14268,6 +14271,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14310,6 +14316,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14352,6 +14361,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14394,6 +14406,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14436,6 +14451,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14478,6 +14496,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14520,6 +14541,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone 6s Plus 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14562,6 +14586,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14604,6 +14631,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "base_unittests_iPhone SE (1st generation) 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14646,6 +14676,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14688,6 +14721,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14730,6 +14766,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14772,6 +14811,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14814,6 +14856,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14856,6 +14901,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14898,6 +14946,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14940,6 +14991,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -14982,6 +15036,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15024,6 +15081,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone 6s Plus 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15066,6 +15126,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15108,6 +15171,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "components_unittests_iPhone SE (1st generation) 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15150,6 +15216,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15192,6 +15261,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15234,6 +15306,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15276,6 +15351,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15318,6 +15396,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15360,6 +15441,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15402,6 +15486,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15444,6 +15531,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone 6s Plus 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15486,6 +15576,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15528,6 +15621,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "gfx_unittests_iPhone SE (1st generation) 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15570,6 +15666,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15612,6 +15711,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15655,6 +15757,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15699,6 +15804,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15743,6 +15851,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15786,6 +15897,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15829,6 +15943,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15873,6 +15990,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15916,6 +16036,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -15958,6 +16081,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16000,6 +16126,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16042,6 +16171,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16084,6 +16216,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16126,6 +16261,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone 6s Plus 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16168,6 +16306,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16210,6 +16351,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_unittests_iPhone SE (1st generation) 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16252,6 +16396,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16294,6 +16441,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16336,6 +16486,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16378,6 +16531,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16420,6 +16576,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16462,6 +16621,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16504,6 +16666,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16546,6 +16711,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16588,6 +16756,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16630,6 +16801,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16672,6 +16846,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16714,6 +16891,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16756,6 +16936,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16798,6 +16981,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone 6s Plus 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16840,6 +17026,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16882,6 +17071,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_inttests_iPhone SE (1st generation) 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16925,6 +17117,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -16968,6 +17163,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17010,6 +17208,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17052,6 +17253,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17094,6 +17298,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17136,6 +17343,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17178,6 +17388,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17220,6 +17433,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone 6s Plus 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17262,6 +17478,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17304,6 +17523,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_unittests_iPhone SE (1st generation) 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17346,6 +17568,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17388,6 +17613,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17430,6 +17658,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17472,6 +17703,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17514,6 +17748,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17556,6 +17793,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone 6s Plus 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17598,6 +17838,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17640,6 +17883,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_inttests_iPhone SE (1st generation) 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17682,6 +17928,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17724,6 +17973,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17766,6 +18018,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17808,6 +18063,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17850,6 +18108,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17892,6 +18153,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone 6s Plus 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17934,6 +18198,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -17976,6 +18243,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_view_unittests_iPhone SE (1st generation) 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18018,6 +18288,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18060,6 +18333,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18102,6 +18378,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18144,6 +18423,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18186,6 +18468,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18228,6 +18513,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18270,6 +18558,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18312,6 +18603,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18354,6 +18648,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18396,6 +18693,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone 6s Plus 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18438,6 +18738,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18480,6 +18783,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "skia_unittests_iPhone SE (1st generation) 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18522,6 +18828,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18564,6 +18873,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18606,6 +18918,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18648,6 +18963,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18690,6 +19008,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18732,6 +19053,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18774,6 +19098,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s Plus 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18816,6 +19143,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone 6s Plus 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18858,6 +19188,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone SE (1st generation) 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18900,6 +19233,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ui_base_unittests_iPhone SE (1st generation) 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18942,6 +19278,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -18984,6 +19323,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19034,6 +19376,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19077,6 +19422,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19120,6 +19468,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19163,6 +19514,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19206,6 +19560,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19249,6 +19606,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19292,6 +19652,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19336,6 +19699,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19380,6 +19746,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19424,6 +19793,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 7 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19468,6 +19840,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19512,6 +19887,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19556,6 +19934,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19600,6 +19981,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone 7 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19644,6 +20028,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19688,6 +20075,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19732,6 +20122,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19775,6 +20168,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19818,6 +20214,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19861,6 +20260,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 7 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19904,6 +20306,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19947,6 +20352,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -19990,6 +20398,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20033,6 +20444,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20076,6 +20490,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20119,6 +20536,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20162,6 +20582,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20206,6 +20629,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20250,6 +20676,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20294,6 +20723,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 7 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20338,6 +20770,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20381,6 +20816,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20424,6 +20862,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20467,6 +20908,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone 7 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20510,6 +20954,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20553,6 +21000,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20596,6 +21046,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20639,6 +21092,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20682,6 +21138,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20725,6 +21184,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone 7 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20768,6 +21230,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20811,6 +21276,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20854,6 +21322,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20897,6 +21368,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20940,6 +21414,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 7 13.6",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -20983,6 +21460,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 7 14.0",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21032,6 +21512,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "absl_hardening_tests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21074,6 +21557,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_crypto_tests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21116,6 +21602,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "boringssl_ssl_tests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21158,6 +21647,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "crypto_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21200,6 +21692,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "google_apis_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21243,6 +21738,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21286,6 +21784,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21329,6 +21830,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21373,6 +21877,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21417,6 +21924,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21461,6 +21971,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_settings_eg2tests_module_iPhone X 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21505,6 +22018,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21548,6 +22064,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21591,6 +22110,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21634,6 +22156,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_smoke_eg2tests_module_iPhone X 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21677,6 +22202,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21721,6 +22249,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21765,6 +22296,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21808,6 +22342,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_chrome_web_eg2tests_module_iPhone X 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21850,6 +22387,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_components_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21892,6 +22432,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_net_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21934,6 +22477,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_remoting_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21977,6 +22523,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22020,6 +22569,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_showcase_eg2tests_module_iPhone X 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22062,6 +22614,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_testing_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22105,6 +22660,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPad Air 2 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22148,6 +22706,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "ios_web_shell_eg2tests_module_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22190,6 +22751,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "net_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22232,6 +22796,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "services_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22274,6 +22841,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "sql_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22316,6 +22886,9 @@
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
         "name": "url_unittests_iPhone 6s 12.4",
+        "resultdb": {
+          "enable": false
+        },
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 2283339..e97316b 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -3208,84 +3208,93 @@
     },
 
     'ios_clang_tests': {
-      'absl_hardening_tests': {},
-      'base_unittests': {},
-      'boringssl_crypto_tests': {},
-      'boringssl_ssl_tests': {},
-      'components_unittests': {},
-      'crypto_unittests': {},
-      'gfx_unittests': {},
-      'google_apis_unittests': {},
-      'ios_chrome_unittests': {},
-      'ios_net_unittests': {},
-      'ios_web_inttests': {},
-      'ios_web_unittests': {},
-      'ios_web_view_inttests': {},
-      'net_unittests': {},
-      'skia_unittests': {},
-      'sql_unittests': {},
-      'ui_base_unittests': {},
-      'url_unittests': {},
+      'absl_hardening_tests': {'resultdb':{'enable':False}},
+      'base_unittests': {'resultdb':{'enable':False}},
+      'boringssl_crypto_tests': {'resultdb':{'enable':False}},
+      'boringssl_ssl_tests': {'resultdb':{'enable':False}},
+      'components_unittests': {'resultdb':{'enable':False}},
+      'crypto_unittests': {'resultdb':{'enable':False}},
+      'gfx_unittests': {'resultdb':{'enable':False}},
+      'google_apis_unittests': {'resultdb':{'enable':False}},
+      'ios_chrome_unittests': {'resultdb':{'enable':False}},
+      'ios_net_unittests': {'resultdb':{'enable':False}},
+      'ios_web_inttests': {'resultdb':{'enable':False}},
+      'ios_web_unittests': {'resultdb':{'enable':False}},
+      'ios_web_view_inttests': {'resultdb':{'enable':False}},
+      'net_unittests': {'resultdb':{'enable':False}},
+      'skia_unittests': {'resultdb':{'enable':False}},
+      'sql_unittests': {'resultdb':{'enable':False}},
+      'ui_base_unittests': {'resultdb':{'enable':False}},
+      'url_unittests': {'resultdb':{'enable':False}},
     },
 
     'ios_common_tests': {
-      'absl_hardening_tests': {},
-      'boringssl_crypto_tests': {},
-      'boringssl_ssl_tests': {},
-      'crypto_unittests': {},
-      'google_apis_unittests': {},
-      'ios_components_unittests': {},
-      'ios_net_unittests': {},
-      'ios_remoting_unittests': {},
-      'ios_testing_unittests': {},
-      'net_unittests': {},
-      'services_unittests': {},
-      'sql_unittests': {},
-      'url_unittests': {},
+      'absl_hardening_tests': {'resultdb':{'enable':False}},
+      'boringssl_crypto_tests': {'resultdb':{'enable':False}},
+      'boringssl_ssl_tests': {'resultdb':{'enable':False}},
+      'crypto_unittests': {'resultdb':{'enable':False}},
+      'google_apis_unittests': {'resultdb':{'enable':False}},
+      'ios_components_unittests': {'resultdb':{'enable':False}},
+      'ios_net_unittests': {'resultdb':{'enable':False}},
+      'ios_remoting_unittests': {'resultdb':{'enable':False}},
+      'ios_testing_unittests': {'resultdb':{'enable':False}},
+      'net_unittests': {'resultdb':{'enable':False}},
+      'services_unittests': {'resultdb':{'enable':False}},
+      'sql_unittests': {'resultdb':{'enable':False}},
+      'url_unittests': {'resultdb':{'enable':False}},
     },
 
     'ios_cronet_tests': {
-      'cronet_test': {},
+      'cronet_test': {'resultdb':{'enable':False}},
     },
 
     'ios_eg2_cq_tests': {
       'ios_chrome_integration_eg2tests_module': {
         'swarming': {
           'shards': 3,
-        }
+        },
+        'resultdb': {
+          'enable': False,
+        },
       },
-      'ios_chrome_signin_eg2tests_module': {},
+      'ios_chrome_signin_eg2tests_module': {'resultdb':{'enable':False}},
       'ios_chrome_ui_eg2tests_module': {
         'swarming': {
           'shards': 5,
-        }
+        },
+        'resultdb': {
+          'enable': False,
+        },
       },
-      'ios_web_shell_eg2tests_module': {},
+      'ios_web_shell_eg2tests_module': {'resultdb':{'enable':False}},
     },
 
     'ios_eg2_tests': {
-      'ios_chrome_bookmarks_eg2tests_module': {},
+      'ios_chrome_bookmarks_eg2tests_module': {'resultdb':{'enable':False}},
       'ios_chrome_settings_eg2tests_module': {
         'swarming': {
           'shards': 3,
         },
+        'resultdb': {
+          'enable': False,
+        },
       },
-      'ios_chrome_smoke_eg2tests_module': {},
-      'ios_chrome_web_eg2tests_module': {},
-      'ios_showcase_eg2tests_module': {},
+      'ios_chrome_smoke_eg2tests_module': {'resultdb':{'enable':False}},
+      'ios_chrome_web_eg2tests_module': {'resultdb':{'enable':False}},
+      'ios_showcase_eg2tests_module': {'resultdb':{'enable':False}},
     },
 
     'ios_screen_size_dependent_tests': {
-      'base_unittests': {},
-      'components_unittests': {},
-      'gfx_unittests': {},
-      'ios_chrome_unittests': {},
-      'ios_web_inttests': {},
-      'ios_web_unittests': {},
-      'ios_web_view_inttests': {},
-      'ios_web_view_unittests': {},
-      'skia_unittests': {},
-      'ui_base_unittests': {},
+      'base_unittests': {'resultdb':{'enable':False}},
+      'components_unittests': {'resultdb':{'enable':False}},
+      'gfx_unittests': {'resultdb':{'enable':False}},
+      'ios_chrome_unittests': {'resultdb':{'enable':False}},
+      'ios_web_inttests': {'resultdb':{'enable':False}},
+      'ios_web_unittests': {'resultdb':{'enable':False}},
+      'ios_web_view_inttests': {'resultdb':{'enable':False}},
+      'ios_web_view_unittests': {'resultdb':{'enable':False}},
+      'skia_unittests': {'resultdb':{'enable':False}},
+      'ui_base_unittests': {'resultdb':{'enable':False}},
     },
 
     # END tests which run on the GPU bots
diff --git a/third_party/blink/common/web_preferences/web_preferences.cc b/third_party/blink/common/web_preferences/web_preferences.cc
index b433e67..d825a36 100644
--- a/third_party/blink/common/web_preferences/web_preferences.cc
+++ b/third_party/blink/common/web_preferences/web_preferences.cc
@@ -200,7 +200,7 @@
       media_controls_enabled(true),
       do_not_update_selection_on_mutating_selection_range(false),
       autoplay_policy(
-          web_pref::AutoplayPolicy::kDocumentUserActivationRequired),
+          blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired),
       low_priority_iframes_threshold(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
       picture_in_picture_enabled(true),
       translate_service_available(false),
diff --git a/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc b/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
index 41103b52..15a8f088 100644
--- a/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
+++ b/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
@@ -112,41 +112,6 @@
 }
 
 // static
-blink::mojom::AutoplayPolicy
-EnumTraits<blink::mojom::AutoplayPolicy, blink::web_pref::AutoplayPolicy>::
-    ToMojom(blink::web_pref::AutoplayPolicy style) {
-  switch (style) {
-    case blink::web_pref::AutoplayPolicy::kNoUserGestureRequired:
-      return blink::mojom::AutoplayPolicy::kNoUserGestureRequired;
-    case blink::web_pref::AutoplayPolicy::kUserGestureRequired:
-      return blink::mojom::AutoplayPolicy::kUserGestureRequired;
-    case blink::web_pref::AutoplayPolicy::kDocumentUserActivationRequired:
-      return blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired;
-  }
-  NOTREACHED();
-  return blink::mojom::AutoplayPolicy::kNoUserGestureRequired;
-}
-
-// static
-bool EnumTraits<blink::mojom::AutoplayPolicy, blink::web_pref::AutoplayPolicy>::
-    FromMojom(blink::mojom::AutoplayPolicy input,
-              blink::web_pref::AutoplayPolicy* out) {
-  switch (input) {
-    case blink::mojom::AutoplayPolicy::kNoUserGestureRequired:
-      *out = blink::web_pref::AutoplayPolicy::kNoUserGestureRequired;
-      return true;
-    case blink::mojom::AutoplayPolicy::kUserGestureRequired:
-      *out = blink::web_pref::AutoplayPolicy::kUserGestureRequired;
-      return true;
-    case blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired:
-      *out = blink::web_pref::AutoplayPolicy::kDocumentUserActivationRequired;
-      return true;
-  }
-  NOTREACHED();
-  return false;
-}
-
-// static
 blink::mojom::EffectiveConnectionType EnumTraits<
     blink::mojom::EffectiveConnectionType,
     net::EffectiveConnectionType>::ToMojom(net::EffectiveConnectionType type) {
@@ -234,7 +199,6 @@
       !data.ReadPrimaryHoverType(&out->primary_hover_type) ||
       !data.ReadViewportStyle(&out->viewport_style) ||
       !data.ReadAnimationPolicy(&out->animation_policy) ||
-      !data.ReadAutoplayPolicy(&out->autoplay_policy) ||
       !data.ReadLowPriorityIframesThreshold(
           &out->low_priority_iframes_threshold) ||
       !data.ReadNetworkQualityEstimatorWebHoldback(
@@ -398,6 +362,7 @@
   out->media_controls_enabled = data.media_controls_enabled();
   out->do_not_update_selection_on_mutating_selection_range =
       data.do_not_update_selection_on_mutating_selection_range();
+  out->autoplay_policy = data.autoplay_policy();
   out->preferred_color_scheme = data.preferred_color_scheme();
   out->picture_in_picture_enabled = data.picture_in_picture_enabled();
   out->translate_service_available = data.translate_service_available();
diff --git a/third_party/blink/manual_tests/forms/color-suggestion-picker.html b/third_party/blink/manual_tests/forms/color-suggestion-picker.html
index 88990f6..f5dd5219 100644
--- a/third_party/blink/manual_tests/forms/color-suggestion-picker.html
+++ b/third_party/blink/manual_tests/forms/color-suggestion-picker.html
@@ -2,82 +2,112 @@
 <html>
 <head>
 <meta charset=utf-8>
-<title>Color Suggestion Picker test</title>
+<title>&lt;input type=color&gt;</title>
 <style>
-body {
+  body {
     background-color: #eeffff;
-}
-iframe {
+  }
+  iframe {
     z-index: 2147483647;
     width: 180px;
     height: 240px;
     border: 0;
     overflow: hidden;
-}
+  }
+  textarea {
+    width: 350px;
+    height: 150px;
+  }
 </style>
 </head>
 <body>
 
-<p>This is a testbed for a color suggestion picker.</p>
+<h3>This is a testbed for &lt;input type=color&gt;</h3>
 
-<div><input type="color" id="color"></div>
-<iframe></iframe>
+<h3>Regular popup &lt;input type=color&gt; <input type="color" id="color"></h3>
 
-<ol id="console" style="font-family:monospace;">
-</ol>
+<h3>Inline iframe &lt;input type=color&gt;</h3>
+<div>Set arguments for the color picker with this textarea.</div>
+<div>The arguments are used inside the picker as "global.params".</div>
+<div>The string must be JSON formatted with double quotes.</div>
+<div><textarea id=argsTextarea></textarea></div>
+<div><button id=restartbutton>Restart picker with args</button></div>
+<br>
+<div id=iframecontainer></div>
+
+<ol id="console" style="font-family:monospace;"></ol>
 
 <script>
-var arguments = {
-    values : ['#000000', '#404040', '#808080', '#c0c0c0', '#ffffff', '#980000', '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#0000ff', '#9900ff', '#ff00ff', '#404040', '#808080', '#c0c0c0', '#ffffff', '#980000', '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#0000ff', '#9900ff', '#ff00ff'],
-    otherColorLabel: 'Other...'
-};
+argsTextarea.textContent = `{
+  "selectedColor": "#aaaaaa"
+}`;
 
-function openColorPicker(args) {
-    var frame = document.getElementsByTagName('iframe')[0];
-    var doc = frame.contentDocument;
-    doc.documentElement.innerHTML = '<head></head><body><div id=main>Loading...</div></body>';
-    var commonCssLink = doc.createElement('link');
-    commonCssLink.rel = 'stylesheet';
-    commonCssLink.href = '../../Source/core/html/forms/resources/pickerCommon.css?' + (new Date()).getTime();
-    doc.head.appendChild(commonCssLink);
-    var link = doc.createElement('link');
-    link.rel = 'stylesheet';
-    link.href = '../../Source/core/html/forms/resources/colorSuggestionPicker.css?' + (new Date()).getTime();
-    doc.head.appendChild(link);
-    var commonJsScript = doc.createElement('script');
-    commonJsScript.src = '../../Source/core/html/forms/resources/pickerCommon.js?' + (new Date()).getTime();
-    doc.body.appendChild(commonJsScript);
-    var script = doc.createElement('script');
-    script.src = '../../Source/core/html/forms/resources/colorSuggestionPicker.js?' + (new Date()).getTime();
-    doc.body.appendChild(script);
+restartbutton.onclick = openColorPicker;
 
-    var pagePopupController = {
-        setValueAndClosePopup: function(numValue, stringValue) {
-            window.log('number=' + numValue + ', string="' + stringValue + '"');
-            if (numValue === 0)
-                window.document.getElementById('color').value = stringValue;
-        },
-        setValue: function(value) {
-            window.log('value="' + value + '"');
-            window.document.getElementById('color').value = value;
-        },
-        closePopup: function() {
-        },
-    }
+function openColorPicker() {
+  const oldFrame = document.getElementById('coloriframe');
+  if (oldFrame)
+    oldFrame.remove();
+  const frame = document.createElement('iframe');
+  frame.id = 'coloriframe';
+  iframecontainer.appendChild(frame);
+  const doc = frame.contentDocument;
 
-    setTimeout(function() {
-        frame.contentWindow.postMessage(JSON.stringify(args), "*");
-        frame.contentWindow.pagePopupController = pagePopupController;
-    }, 100);
+  // The following code sets up a color picker inside an iframe as similarly as
+  // possible to ColorChooserPopupUIController::WriteColorPickerDocument.
+  // https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc;l=97;drc=cc7f2a9e51671f702fd5e6a07c0ffda834fa8a38
+
+  doc.documentElement.innerHTML = `
+    <head>
+      <meta charset='UTF-8'>
+      <link rel=stylesheet href="../../renderer/core/html/forms/resources/pickerCommon.css">
+      <link rel=stylesheet href="../../renderer/core/html/forms/resources/color_picker.css">
+    </head>
+    <body>
+      <div id=main>Loading...</div>
+    </body>
+  `;
+
+  const pickerCommon = doc.createElement('script');
+  pickerCommon.src = "../../renderer/core/html/forms/resources/pickerCommon.js";
+  doc.body.appendChild(pickerCommon);
+
+  const colorPicker = doc.createElement('script');
+  colorPicker.src = "../../renderer/core/html/forms/resources/color_picker.js";
+  doc.body.appendChild(colorPicker);
+
+  const colorPickerCommon = doc.createElement('script');
+  colorPickerCommon.src = "../../renderer/core/html/forms/resources/color_picker_common.js";
+  doc.body.appendChild(colorPickerCommon);
+
+  const pagePopupController = frame.contentWindow.pagePopupController = {
+    setValueAndClosePopup: function(numValue, stringValue) {
+      window.log('number=' + numValue + ', string="' + stringValue + '"');
+      if (numValue === 0)
+        window.document.getElementById('color').value = stringValue;
+    },
+    setValue: function(value) {
+      window.log('value="' + value + '"');
+      window.document.getElementById('color').value = value;
+    },
+    closePopup: function() {
+    },
+  };
+
+  setTimeout(function() {
+    frame.contentWindow.postMessage(argsTextarea.textContent, "*");
+    frame.contentWindow.pagePopupController = pagePopupController;
+  }, 100);
 }
 
 function log(str) {
-    var entry = document.createElement('li');
-    entry.innerText = str;
-    document.getElementById('console').appendChild(entry);
+  var entry = document.createElement('li');
+  entry.innerText = str;
+  document.getElementById('console').appendChild(entry);
 }
 
-openColorPicker(arguments);
+openColorPicker();
+
 </script>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index d8538dd..7eaffcd 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -189,7 +189,6 @@
     "web_cache/web_cache_resource_type_stats.h",
     "web_package/signed_exchange_consts.h",
     "web_package/web_package_request_matcher.h",
-    "web_preferences/autoplay_policy.h",
     "web_preferences/viewport_style.h",
     "web_preferences/web_preferences.h",
     "widget/device_emulation_params.h",
diff --git a/third_party/blink/public/common/web_preferences/autoplay_policy.h b/third_party/blink/public/common/web_preferences/autoplay_policy.h
deleted file mode 100644
index e7ace33..0000000
--- a/third_party/blink/public/common/web_preferences/autoplay_policy.h
+++ /dev/null
@@ -1,21 +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.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_WEB_PREFERENCES_AUTOPLAY_POLICY_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_WEB_PREFERENCES_AUTOPLAY_POLICY_H_
-
-namespace blink {
-namespace web_pref {
-
-// Defines the autoplay policy to be used.
-enum class AutoplayPolicy {
-  kNoUserGestureRequired,
-  kUserGestureRequired,
-  kDocumentUserActivationRequired,
-};
-
-}  // namespace web_pref
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_WEB_PREFERENCES_AUTOPLAY_POLICY_H_
diff --git a/third_party/blink/public/common/web_preferences/web_preferences.h b/third_party/blink/public/common/web_preferences/web_preferences.h
index 85ad421..7761279 100644
--- a/third_party/blink/public/common/web_preferences/web_preferences.h
+++ b/third_party/blink/public/common/web_preferences/web_preferences.h
@@ -14,7 +14,6 @@
 #include "build/build_config.h"
 #include "net/nqe/effective_connection_type.h"
 #include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/web_preferences/autoplay_policy.h"
 #include "third_party/blink/public/common/web_preferences/viewport_style.h"
 #include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom-shared.h"
 #include "third_party/blink/public/mojom/v8_cache_options.mojom-forward.h"
@@ -286,7 +285,8 @@
   bool do_not_update_selection_on_mutating_selection_range;
 
   // Defines the current autoplay policy.
-  AutoplayPolicy autoplay_policy;
+  blink::mojom::AutoplayPolicy autoplay_policy =
+      blink::mojom::AutoplayPolicy::kNoUserGestureRequired;
 
   // The preferred color scheme for the web content. The scheme is used to
   // evaluate the prefers-color-scheme media query and resolve UA color scheme
diff --git a/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h b/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
index aff1ec1..dc5f1be 100644
--- a/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
+++ b/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
@@ -9,7 +9,6 @@
 #include "mojo/public/cpp/bindings/struct_traits.h"
 #include "net/nqe/effective_connection_type.h"
 #include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/web_preferences/autoplay_policy.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 #include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h"
 #include "ui/base/pointer/pointer_device.h"
@@ -42,16 +41,6 @@
 };
 
 template <>
-struct BLINK_COMMON_EXPORT
-    EnumTraits<blink::mojom::AutoplayPolicy, blink::web_pref::AutoplayPolicy> {
-  static blink::mojom::AutoplayPolicy ToMojom(
-      blink::web_pref::AutoplayPolicy policy);
-
-  static bool FromMojom(blink::mojom::AutoplayPolicy input,
-                        blink::web_pref::AutoplayPolicy* out);
-};
-
-template <>
 struct BLINK_COMMON_EXPORT EnumTraits<blink::mojom::EffectiveConnectionType,
                                       net::EffectiveConnectionType> {
   static blink::mojom::EffectiveConnectionType ToMojom(
@@ -728,7 +717,7 @@
     return r.do_not_update_selection_on_mutating_selection_range;
   }
 
-  static blink::web_pref::AutoplayPolicy autoplay_policy(
+  static blink::mojom::AutoplayPolicy autoplay_policy(
       const blink::web_pref::WebPreferences& r) {
     return r.autoplay_policy;
   }
diff --git a/third_party/blink/public/web/web_settings.h b/third_party/blink/public/web/web_settings.h
index e80a1b7..2a27862 100644
--- a/third_party/blink/public/web/web_settings.h
+++ b/third_party/blink/public/web/web_settings.h
@@ -114,7 +114,7 @@
   virtual void SetAlwaysShowContextMenuOnTouch(bool) = 0;
   virtual void SetAntialiased2dCanvasEnabled(bool) = 0;
   virtual void SetAntialiasedClips2dCanvasEnabled(bool) = 0;
-  virtual void SetAutoplayPolicy(web_pref::AutoplayPolicy) = 0;
+  virtual void SetAutoplayPolicy(mojom::AutoplayPolicy) = 0;
   virtual void SetAutoZoomFocusedNodeToLegibleScale(bool) = 0;
   virtual void SetCaretBrowsingEnabled(bool) = 0;
   virtual void SetClobberUserAgentInitialScaleQuirk(bool) = 0;
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni
index 317eac0..33111dbf 100644
--- a/third_party/blink/renderer/bindings/idl_in_modules.gni
+++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -661,7 +661,6 @@
           "//third_party/blink/renderer/modules/virtualkeyboard/navigator_virtual_keyboard.idl",
           "//third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.idl",
           "//third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.idl",
-          "//third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event_init.idl",
           "//third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.idl",
           "//third_party/blink/renderer/modules/wake_lock/wake_lock.idl",
           "//third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.idl",
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/callback_interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/callback_interface.py
index 4a6df51..7d8cea4 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/callback_interface.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/callback_interface.py
@@ -202,7 +202,8 @@
     ])
     installer_function_defs.accumulate(
         CodeGenAccumulator.require_include_headers([
-            "third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.h"
+            "third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.h",
+            "third_party/blink/renderer/platform/bindings/idl_member_installer.h",
         ]))
 
     # WrapperTypeInfo
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 ca6c2d2..5828b08 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -4266,18 +4266,16 @@
             code_node.register_code_symbol(symbol_node)
 
 
-def _make_property_entry_cached_accessor(property_):
-    value = property_.extended_attributes.value_of("CachedAccessor")
-    return "V8PrivateProperty::CachedAccessor::{}".format(value or "kNone")
-
-
-def _make_property_entry_check_cross_origin_access(property_,
-                                                   is_get=False,
-                                                   is_set=False):
+def _make_property_entry_cross_origin_check(property_,
+                                            is_get=False,
+                                            is_set=False):
     constants = {
-        True: "V8DOMConfiguration::kDoNotCheckAccess",
-        False: "V8DOMConfiguration::kCheckAccess",
+        False: "unsigned(IDLMemberInstaller::FlagCrossOriginCheck::kCheck)",
+        True:
+        "unsigned(IDLMemberInstaller::FlagCrossOriginCheck::kDoNotCheck)",
     }
+    if property_.is_static:
+        return constants[True]
     if "CrossOrigin" not in property_.extended_attributes:
         return constants[False]
     values = property_.extended_attributes.values_of("CrossOrigin")
@@ -4289,54 +4287,26 @@
         return constants[True]
 
 
-def _make_property_entry_check_receiver(property_):
+def _make_property_entry_location(property_):
+    if hasattr(property_, "is_static") and property_.is_static:
+        return "unsigned(IDLMemberInstaller::FlagLocation::kInterface)"
+    if "Global" in property_.owner.extended_attributes:
+        return "unsigned(IDLMemberInstaller::FlagLocation::kInstance)"
+    if "LegacyUnforgeable" in property_.extended_attributes:
+        return "unsigned(IDLMemberInstaller::FlagLocation::kInstance)"
+    return "unsigned(IDLMemberInstaller::FlagLocation::kPrototype)"
+
+
+def _make_property_entry_receiver_check(property_):
     if ("LegacyLenientThis" in property_.extended_attributes
+            or property_.is_static
             or (isinstance(property_, web_idl.Attribute)
                 and property_.idl_type.unwrap().is_promise)
             or (isinstance(property_, web_idl.OverloadGroup)
                 and property_[0].return_type.unwrap().is_promise)):
-        return "V8DOMConfiguration::kDoNotCheckHolder"
+        return "unsigned(IDLMemberInstaller::FlagReceiverCheck::kDoNotCheck)"
     else:
-        return "V8DOMConfiguration::kCheckHolder"
-
-
-def _make_property_entry_constant_type_and_value_format(property_):
-    idl_type = property_.idl_type.unwrap()
-    if (idl_type.keyword_typename == "long long"
-            or idl_type.keyword_typename == "unsigned long long"):
-        assert False, "64-bit constants are not yet supported."
-    if idl_type.keyword_typename == "unsigned long":
-        return ("V8DOMConfiguration::kConstantTypeUnsignedLong",
-                "static_cast<int>({value})")
-    if idl_type.is_integer:
-        return ("V8DOMConfiguration::kConstantTypeLong",
-                "static_cast<int>({value})")
-    if idl_type.is_floating_point_numeric:
-        return ("V8DOMConfiguration::kConstantTypeDouble",
-                "static_cast<double>({value})")
-    assert False, "Unsupported type: {}".format(idl_type.syntactic_form)
-
-
-def _make_property_entry_has_side_effect(property_):
-    if property_.extended_attributes.value_of("Affects") == "Nothing":
-        return "V8DOMConfiguration::kHasNoSideEffect"
-    else:
-        return "V8DOMConfiguration::kHasSideEffect"
-
-
-def _make_property_entry_on_which_object(property_):
-    ON_INSTANCE = "V8DOMConfiguration::kOnInstance"
-    ON_PROTOTYPE = "V8DOMConfiguration::kOnPrototype"
-    ON_INTERFACE = "V8DOMConfiguration::kOnInterface"
-    if isinstance(property_, web_idl.Constant):
-        return ON_INTERFACE
-    if hasattr(property_, "is_static") and property_.is_static:
-        return ON_INTERFACE
-    if "Global" in property_.owner.extended_attributes:
-        return ON_INSTANCE
-    if "LegacyUnforgeable" in property_.extended_attributes:
-        return ON_INSTANCE
-    return ON_PROTOTYPE
+        return "unsigned(IDLMemberInstaller::FlagReceiverCheck::kCheck)"
 
 
 def _make_property_entry_v8_c_function(entry):
@@ -4346,6 +4316,11 @@
         entry.no_alloc_direct_callback_name)
 
 
+def _make_property_entry_v8_cached_accessor(property_):
+    return "unsigned(V8PrivateProperty::CachedAccessor::{})".format(
+        property_.extended_attributes.value_of("CachedAccessor") or "kNone")
+
+
 def _make_property_entry_v8_property_attribute(property_):
     values = []
     if "NotEnumerable" in property_.extended_attributes:
@@ -4357,19 +4332,25 @@
     if not values:
         values.append("v8::None")
     if len(values) == 1:
-        return values[0]
+        return "unsigned({})".format(values[0])
     else:
-        return "static_cast<v8::PropertyAttribute>({})".format(
-            " | ".join(values))
+        return "unsigned({})".format(" | ".join(values))
+
+
+def _make_property_entry_v8_side_effect(property_):
+    if property_.extended_attributes.value_of("Affects") == "Nothing":
+        return "unsigned(v8::SideEffectType::kHasNoSideEffect)"
+    else:
+        return "unsigned(v8::SideEffectType::kHasSideEffect)"
 
 
 def _make_property_entry_world(world):
     if world == CodeGenContext.MAIN_WORLD:
-        return "V8DOMConfiguration::kMainWorld"
+        return "unsigned(IDLMemberInstaller::FlagWorld::kMainWorld)"
     if world == CodeGenContext.NON_MAIN_WORLDS:
-        return "V8DOMConfiguration::kNonMainWorlds"
+        return "unsigned(IDLMemberInstaller::FlagWorld::kNonMainWorlds)"
     if world == CodeGenContext.ALL_WORLDS:
-        return "V8DOMConfiguration::kAllWorlds"
+        return "unsigned(IDLMemberInstaller::FlagWorld::kAllWorlds)"
     assert False
 
 
@@ -4387,42 +4368,41 @@
                    "\"{property_name}\", "
                    "{attribute_get_callback}, "
                    "{attribute_set_callback}, "
-                   "static_cast<unsigned>({cached_accessor}), "
                    "{v8_property_attribute}, "
-                   "{on_which_object}, "
-                   "{check_receiver}, "
-                   "{check_cross_origin_get_access}, "
-                   "{check_cross_origin_set_access}, "
-                   "{has_side_effect}, "
-                   "{world}"
+                   "{location}, "
+                   "{world}, "
+                   "{receiver_check}, "
+                   "{cross_origin_check_for_get}, "
+                   "{cross_origin_check_for_set}, "
+                   "{v8_side_effect}, "
+                   "{v8_cached_accessor}"
                    "}},")
         text = _format(
             pattern,
             property_name=entry.property_.identifier,
             attribute_get_callback=entry.attr_get_callback_name,
             attribute_set_callback=(entry.attr_set_callback_name or "nullptr"),
-            cached_accessor=_make_property_entry_cached_accessor(
-                entry.property_),
             v8_property_attribute=_make_property_entry_v8_property_attribute(
                 entry.property_),
-            on_which_object=_make_property_entry_on_which_object(
+            location=_make_property_entry_location(entry.property_),
+            world=_make_property_entry_world(entry.world),
+            receiver_check=_make_property_entry_receiver_check(
                 entry.property_),
-            check_receiver=_make_property_entry_check_receiver(
+            cross_origin_check_for_get=(
+                _make_property_entry_cross_origin_check(entry.property_,
+                                                        is_get=True)),
+            cross_origin_check_for_set=(
+                _make_property_entry_cross_origin_check(entry.property_,
+                                                        is_set=True)),
+            v8_side_effect=_make_property_entry_v8_side_effect(
                 entry.property_),
-            check_cross_origin_get_access=(
-                _make_property_entry_check_cross_origin_access(entry.property_,
-                                                               is_get=True)),
-            check_cross_origin_set_access=(
-                _make_property_entry_check_cross_origin_access(entry.property_,
-                                                               is_set=True)),
-            has_side_effect=_make_property_entry_has_side_effect(
-                entry.property_),
-            world=_make_property_entry_world(entry.world))
+            v8_cached_accessor=_make_property_entry_v8_cached_accessor(
+                entry.property_))
         entry_nodes.append(T(text))
 
     return ListNode([
-        T("static constexpr const V8DOMConfiguration::AccessorConfiguration " +
-          table_name + "[] = {"),
+        T("static const IDLMemberInstaller::AttributeConfig " + table_name +
+          "[] = {"),
         ListNode(entry_nodes),
         T("};"),
     ])
@@ -4448,9 +4428,8 @@
         entry_nodes.append(T(text))
 
     return ListNode([
-        T("static constexpr const "
-          "V8DOMConfiguration::ConstantCallbackConfiguration " + table_name +
-          "[] = {"),
+        T("static const IDLMemberInstaller::ConstantCallbackConfig " +
+          table_name + "[] = {"),
         ListNode(entry_nodes),
         T("};"),
     ])
@@ -4469,23 +4448,15 @@
     for entry in constant_entries:
         pattern = ("{{"
                    "\"{property_name}\", "
-                   "{constant_type}, "
                    "{constant_value}"
                    "}},")
-        constant_type, constant_value_fmt = (
-            _make_property_entry_constant_type_and_value_format(
-                entry.property_))
-        constant_value = _format(
-            constant_value_fmt, value=entry.const_constant_name)
-        text = _format(
-            pattern,
-            property_name=entry.property_.identifier,
-            constant_type=constant_type,
-            constant_value=constant_value)
+        text = _format(pattern,
+                       property_name=entry.property_.identifier,
+                       constant_value=entry.const_constant_name)
         entry_nodes.append(T(text))
 
     return ListNode([
-        T("static constexpr const V8DOMConfiguration::ConstantConfiguration " +
+        T("static const IDLMemberInstaller::ConstantValueConfig " +
           table_name + "[] = {"),
         ListNode(entry_nodes),
         T("};"),
@@ -4506,25 +4477,16 @@
     for entry in exposed_construct_entries:
         pattern = ("{{"
                    "\"{property_name}\", "
-                   "{exposed_construct_callback}, "
-                   "nullptr, "
-                   "static_cast<v8::PropertyAttribute>(v8::DontEnum), "
-                   "V8DOMConfiguration::kOnInstance, "
-                   "V8DOMConfiguration::kDoNotCheckHolder, "
-                   "V8DOMConfiguration::kHasNoSideEffect, "
-                   "V8DOMConfiguration::kReplaceWithDataProperty, "
-                   "{world}"
+                   "{exposed_construct_callback}"
                    "}}, ")
-        text = _format(
-            pattern,
-            property_name=entry.property_.identifier,
-            exposed_construct_callback=entry.prop_callback_name,
-            world=_make_property_entry_world(entry.world))
+        text = _format(pattern,
+                       property_name=entry.property_.identifier,
+                       exposed_construct_callback=entry.prop_callback_name)
         entry_nodes.append(T(text))
 
     return ListNode([
-        T("static constexpr const V8DOMConfiguration::AttributeConfiguration "
-          + table_name + "[] = {"),
+        T("static const IDLMemberInstaller::ExposedConstructConfig " +
+          table_name + "[] = {"),
         ListNode(entry_nodes),
         T("};"),
     ])
@@ -4554,11 +4516,11 @@
                    "{operation_callback}, "
                    "{function_length}, "
                    "{v8_property_attribute}, "
-                   "{on_which_object}, "
-                   "{check_receiver}, "
-                   "{check_cross_origin_access}, "
-                   "{has_side_effect}, "
-                   "{world}"
+                   "{location}, "
+                   "{world}, "
+                   "{receiver_check}, "
+                   "{cross_origin_check}, "
+                   "{v8_side_effect}"
                    "}}, ")
         if no_alloc_direct_call_enabled:
             pattern = "{{" + pattern + "{v8_c_function}}}, "
@@ -4569,24 +4531,23 @@
             function_length=entry.op_func_length,
             v8_property_attribute=_make_property_entry_v8_property_attribute(
                 entry.property_),
-            on_which_object=_make_property_entry_on_which_object(
-                entry.property_),
-            check_receiver=_make_property_entry_check_receiver(
-                entry.property_),
-            check_cross_origin_access=(
-                _make_property_entry_check_cross_origin_access(
-                    entry.property_)),
-            has_side_effect=_make_property_entry_has_side_effect(
-                entry.property_),
+            location=_make_property_entry_location(entry.property_),
             world=_make_property_entry_world(entry.world),
+            receiver_check=_make_property_entry_receiver_check(
+                entry.property_),
+            cross_origin_check=_make_property_entry_cross_origin_check(
+                entry.property_),
+            v8_side_effect=_make_property_entry_v8_side_effect(
+                entry.property_),
             v8_c_function=_make_property_entry_v8_c_function(entry))
         entry_nodes.append(T(text))
 
     table_decl_before_name = (
-        "static constexpr const V8DOMConfiguration::MethodConfiguration")
+        "static const IDLMemberInstaller::OperationConfig")
     if no_alloc_direct_call_enabled:
-        table_decl_before_name = ("static const V8DOMConfiguration::"
-                                  "NoAllocDirectCallMethodConfiguration")
+        table_decl_before_name = (
+            "static const "
+            "IDLMemberInstaller::NoAllocDirectCallOperationConfig")
     return ListNode([
         T(table_decl_before_name + " " + table_name + "[] = {"),
         ListNode(entry_nodes),
@@ -5480,6 +5441,11 @@
             body.add_template_var(arg_name, arg_name)
     bind_installer_local_vars(body, cg_context)
 
+    body.extend([
+        TextNode("using bindings::IDLMemberInstaller;"),
+        EmptyNode(),
+    ])
+
     if (is_per_context_install
             and "Global" in cg_context.interface.extended_attributes):
         body.extend([
@@ -5531,32 +5497,34 @@
                     ]))
         body.append(EmptyNode())
 
-    table_name = "kAttributeTable"
     if is_per_context_install:
-        installer_call_text = (
-            "V8DOMConfiguration::InstallAccessors(${isolate}, ${world}, "
-            "${instance_object}, ${prototype_object}, ${interface_object}, "
-            "${signature}, kAttributeTable, base::size(kAttributeTable));")
+        pattern = ("{install_func}("
+                   "${isolate}, ${world}, "
+                   "v8::Local<v8::Object>(${instance_object}), "
+                   "v8::Local<v8::Object>(${prototype_object}), "
+                   "v8::Local<v8::Object>(${interface_object}), "
+                   "${signature}, {table_name});")
     else:
-        installer_call_text = (
-            "V8DOMConfiguration::InstallAccessors(${isolate}, ${world}, "
-            "${instance_template}, ${prototype_template}, "
-            "${interface_template}, ${signature}, "
-            "kAttributeTable, base::size(kAttributeTable));")
+        pattern = ("{install_func}("
+                   "${isolate}, ${world}, "
+                   "v8::Local<v8::Template>(${instance_template}), "
+                   "v8::Local<v8::Template>(${prototype_template}), "
+                   "v8::Local<v8::Template>(${interface_template}), "
+                   "${signature}, {table_name});")
+
+    table_name = "kAttributeTable"
+    installer_call_text = _format(
+        pattern,
+        install_func="IDLMemberInstaller::InstallAttributes",
+        table_name=table_name)
     install_properties(table_name, attribute_entries,
                        _make_attribute_registration_table, installer_call_text)
 
     table_name = "kConstantCallbackTable"
-    if is_per_context_install:
-        installer_call_text = (
-            "V8DOMConfiguration::InstallConstants(${isolate}, "
-            "${interface_object}, ${prototype_object}, "
-            "kConstantCallbackTable, base::size(kConstantCallbackTable));")
-    else:
-        installer_call_text = (
-            "V8DOMConfiguration::InstallConstants(${isolate}, "
-            "${interface_template}, ${prototype_template}, "
-            "kConstantCallbackTable, base::size(kConstantCallbackTable));")
+    installer_call_text = _format(
+        pattern,
+        install_func="IDLMemberInstaller::InstallConstants",
+        table_name=table_name)
     constant_callback_entries = filter(lambda entry: entry.const_callback_name,
                                        constant_entries)
     install_properties(table_name, constant_callback_entries,
@@ -5564,16 +5532,10 @@
                        installer_call_text)
 
     table_name = "kConstantValueTable"
-    if is_per_context_install:
-        installer_call_text = (
-            "V8DOMConfiguration::InstallConstants(${isolate}, "
-            "${interface_object}, ${prototype_object}, "
-            "kConstantValueTable, base::size(kConstantValueTable));")
-    else:
-        installer_call_text = (
-            "V8DOMConfiguration::InstallConstants(${isolate}, "
-            "${interface_template}, ${prototype_template}, "
-            "kConstantValueTable, base::size(kConstantValueTable));")
+    installer_call_text = _format(
+        pattern,
+        install_func="IDLMemberInstaller::InstallConstants",
+        table_name=table_name)
     constant_value_entries = filter(
         lambda entry: not entry.const_callback_name, constant_entries)
     install_properties(table_name, constant_value_entries,
@@ -5581,32 +5543,19 @@
                        installer_call_text)
 
     table_name = "kExposedConstructTable"
-    if is_per_context_install:
-        installer_call_text = (
-            "V8DOMConfiguration::InstallAttributes(${isolate}, ${world}, "
-            "${instance_object}, ${prototype_object}, "
-            "kExposedConstructTable, base::size(kExposedConstructTable));")
-    else:
-        installer_call_text = (
-            "V8DOMConfiguration::InstallAttributes(${isolate}, ${world}, "
-            "${instance_template}, ${prototype_template}, "
-            "kExposedConstructTable, base::size(kExposedConstructTable));")
+    installer_call_text = _format(
+        pattern,
+        install_func="IDLMemberInstaller::InstallExposedConstructs",
+        table_name=table_name)
     install_properties(table_name, exposed_construct_entries,
                        _make_exposed_construct_registration_table,
                        installer_call_text)
 
     table_name = "kOperationTable"
-    if is_per_context_install:
-        installer_call_text = (
-            "V8DOMConfiguration::InstallMethods(${isolate}, ${world}, "
-            "${instance_object}, ${prototype_object}, ${interface_object}, "
-            "${signature}, kOperationTable, base::size(kOperationTable));")
-    else:
-        installer_call_text = (
-            "V8DOMConfiguration::InstallMethods(${isolate}, ${world}, "
-            "${instance_template}, ${prototype_template}, "
-            "${interface_template}, ${signature}, "
-            "kOperationTable, base::size(kOperationTable));")
+    installer_call_text = _format(
+        pattern,
+        install_func="IDLMemberInstaller::InstallOperations",
+        table_name=table_name)
     entries = filter(lambda entry: not entry.no_alloc_direct_callback_name,
                      operation_entries)
     install_properties(table_name, entries, _make_operation_registration_table,
@@ -6956,6 +6905,7 @@
         "third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.h",
         "third_party/blink/renderer/bindings/core/v8/v8_set_return_value_for_core.h",
         "third_party/blink/renderer/platform/bindings/exception_messages.h",
+        "third_party/blink/renderer/platform/bindings/idl_member_installer.h",
         "third_party/blink/renderer/platform/bindings/runtime_call_stats.h",
         "third_party/blink/renderer/platform/bindings/v8_binding.h",
     ])
diff --git a/third_party/blink/renderer/config.gni b/third_party/blink/renderer/config.gni
index d57b607d..131711a7 100644
--- a/third_party/blink/renderer/config.gni
+++ b/third_party/blink/renderer/config.gni
@@ -43,11 +43,11 @@
 
   # If true, the new implementation (experimental) of Blink-V8 bindings
   # (of IDL callback function) is used.
-  use_blink_v8_binding_new_idl_callback_function = false
+  use_blink_v8_binding_new_idl_callback_function = true
 
   # If true, the new implementation (experimental) of Blink-V8 bindings
   # (of IDL callback interface) is used.
-  use_blink_v8_binding_new_idl_callback_interface = false
+  use_blink_v8_binding_new_idl_callback_interface = true
 
   # If true, the new implementation (experimental) of Blink-V8 bindings
   # (of IDL dictionary) is used.
diff --git a/third_party/blink/renderer/core/content_capture/BUILD.gn b/third_party/blink/renderer/core/content_capture/BUILD.gn
index 88c7a65..e496c5a 100644
--- a/third_party/blink/renderer/core/content_capture/BUILD.gn
+++ b/third_party/blink/renderer/core/content_capture/BUILD.gn
@@ -16,8 +16,6 @@
     "content_capture_task_histogram_reporter.h",
     "content_holder.cc",
     "content_holder.h",
-    "sent_nodes.cc",
-    "sent_nodes.h",
     "task_session.cc",
     "task_session.h",
   ]
diff --git a/third_party/blink/renderer/core/content_capture/content_capture_manager.cc b/third_party/blink/renderer/core/content_capture/content_capture_manager.cc
index 06d0da1d..6c6901f 100644
--- a/third_party/blink/renderer/core/content_capture/content_capture_manager.cc
+++ b/third_party/blink/renderer/core/content_capture/content_capture_manager.cc
@@ -5,7 +5,6 @@
 #include "third_party/blink/renderer/core/content_capture/content_capture_manager.h"
 
 #include "base/time/time.h"
-#include "third_party/blink/renderer/core/content_capture/sent_nodes.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/layout/layout_text.h"
 
@@ -29,8 +28,7 @@
 ContentCaptureManager::ContentCaptureManager(LocalFrame& local_frame_root)
     : local_frame_root_(&local_frame_root) {
   DCHECK(local_frame_root.IsLocalRoot());
-  sent_nodes_ = MakeGarbageCollected<SentNodes>();
-  task_session_ = MakeGarbageCollected<TaskSession>(*sent_nodes_);
+  task_session_ = MakeGarbageCollected<TaskSession>();
 }
 
 ContentCaptureManager::~ContentCaptureManager() = default;
@@ -114,7 +112,6 @@
   visitor->Trace(content_capture_idle_task_);
   visitor->Trace(local_frame_root_);
   visitor->Trace(task_session_);
-  visitor->Trace(sent_nodes_);
   visitor->Trace(latest_user_activation_);
 }
 
diff --git a/third_party/blink/renderer/core/content_capture/content_capture_manager.h b/third_party/blink/renderer/core/content_capture/content_capture_manager.h
index 66253c5..d6431c88 100644
--- a/third_party/blink/renderer/core/content_capture/content_capture_manager.h
+++ b/third_party/blink/renderer/core/content_capture/content_capture_manager.h
@@ -16,7 +16,6 @@
 
 class LocalFrame;
 class Node;
-class SentNodes;
 
 // This class is used to create the NodeHolder, and start the ContentCaptureTask
 // when necessary. The ContentCaptureManager is owned by main frame.
@@ -83,9 +82,6 @@
 
   Member<TaskSession> task_session_;
 
-  // A set of weak reference of the node that has been sent.
-  Member<SentNodes> sent_nodes_;
-
   // The latest user activation in any frame of the |local_frame_root_|.
   Member<UserActivation> latest_user_activation_;
 };
diff --git a/third_party/blink/renderer/core/content_capture/sent_nodes.cc b/third_party/blink/renderer/core/content_capture/sent_nodes.cc
deleted file mode 100644
index 24a6cbd..0000000
--- a/third_party/blink/renderer/core/content_capture/sent_nodes.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2019 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/content_capture/sent_nodes.h"
-
-#include "third_party/blink/renderer/core/dom/node.h"
-
-namespace blink {
-
-bool SentNodes::HasSent(const Node& node) {
-  return sent_nodes_.Contains(&node);
-}
-
-void SentNodes::OnSent(const Node& node) {
-  sent_nodes_.insert(WeakMember<const Node>(&node));
-}
-
-void SentNodes::Trace(Visitor* visitor) const {
-  visitor->Trace(sent_nodes_);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/content_capture/sent_nodes.h b/third_party/blink/renderer/core/content_capture/sent_nodes.h
deleted file mode 100644
index ca7b197b..0000000
--- a/third_party/blink/renderer/core/content_capture/sent_nodes.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2019 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_CONTENT_CAPTURE_SENT_NODES_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_CONTENT_CAPTURE_SENT_NODES_H_
-
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
-#include "third_party/blink/renderer/platform/heap/member.h"
-
-namespace blink {
-
-class Node;
-
-// The class manages a list of nodes that have been sent, is only used when
-// kNodeID is used, see WebContentCaptureClient::GetNodeType().
-class SentNodes final : public GarbageCollected<SentNodes> {
- public:
-  bool HasSent(const Node& node);
-  void OnSent(const Node& node);
-
-  void Trace(Visitor*) const;
-
- private:
-  HeapHashSet<WeakMember<const Node>> sent_nodes_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CONTENT_CAPTURE_SENT_NODES_H_
diff --git a/third_party/blink/renderer/core/content_capture/task_session.cc b/third_party/blink/renderer/core/content_capture/task_session.cc
index 699dcfa..ae55385a 100644
--- a/third_party/blink/renderer/core/content_capture/task_session.cc
+++ b/third_party/blink/renderer/core/content_capture/task_session.cc
@@ -6,15 +6,15 @@
 
 #include <utility>
 
-#include "third_party/blink/renderer/core/content_capture/sent_nodes.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/dom_node_ids.h"
 
 namespace blink {
 
-TaskSession::DocumentSession::DocumentSession(const Document& document,
-                                              SentNodes& sent_nodes,
-                                              SentNodeCountCallback& callback)
+TaskSession::DocumentSession::DocumentSession(
+    const Document& document,
+    HeapHashSet<WeakMember<const Node>>& sent_nodes,
+    SentNodeCountCallback& callback)
     : document_(&document), sent_nodes_(&sent_nodes), callback_(callback) {}
 
 TaskSession::DocumentSession::~DocumentSession() {
@@ -46,8 +46,8 @@
   while (!captured_content_.IsEmpty()) {
     auto node = captured_content_.begin()->key;
     const gfx::Rect rect = captured_content_.Take(node);
-    if (node && node->GetLayoutObject() && !sent_nodes_->HasSent(*node)) {
-      sent_nodes_->OnSent(*node);
+    if (node && node->GetLayoutObject() && !sent_nodes_->Contains(node)) {
+      sent_nodes_->insert(WeakMember<const Node>(node));
       total_sent_nodes_++;
       return MakeGarbageCollected<ContentHolder>(node, rect);
     }
@@ -69,7 +69,6 @@
 
 void TaskSession::DocumentSession::Trace(Visitor* visitor) const {
   visitor->Trace(captured_content_);
-  visitor->Trace(sent_nodes_);
   visitor->Trace(document_);
   visitor->Trace(changed_content_);
 }
@@ -80,7 +79,7 @@
   detached_nodes_.Clear();
 }
 
-TaskSession::TaskSession(SentNodes& sent_nodes) : sent_nodes_(sent_nodes) {}
+TaskSession::TaskSession() = default;
 
 TaskSession::DocumentSession* TaskSession::GetNextUnsentDocumentSession() {
   for (auto& doc : to_document_session_.Values()) {
@@ -109,7 +108,7 @@
     if (Node* node = DOMNodeIds::NodeForId(i.node_id)) {
       if (changed_nodes_.Take(node)) {
         // The changed node might not be sent.
-        if (sent_nodes_->HasSent(*node)) {
+        if (sent_nodes_.Contains(node)) {
           EnsureDocumentSession(node->GetDocument())
               .AddChangedNode(*node, i.visual_rect);
         } else {
@@ -118,7 +117,7 @@
         }
         continue;
       }
-      if (!sent_nodes_->HasSent(*node)) {
+      if (!sent_nodes_.Contains(node)) {
         EnsureDocumentSession(node->GetDocument())
             .AddCapturedNode(*node, i.visual_rect);
       }
@@ -127,7 +126,7 @@
 }
 
 void TaskSession::OnNodeDetached(const Node& node) {
-  if (sent_nodes_->HasSent(node)) {
+  if (sent_nodes_.Contains(&node)) {
     EnsureDocumentSession(node.GetDocument())
         .AddDetachedNode(reinterpret_cast<int64_t>(&node));
     has_unsent_data_ = true;
@@ -143,7 +142,7 @@
   DocumentSession* doc_session = GetDocumentSession(doc);
   if (!doc_session) {
     doc_session =
-        MakeGarbageCollected<DocumentSession>(doc, *sent_nodes_, callback_);
+        MakeGarbageCollected<DocumentSession>(doc, sent_nodes_, callback_);
     to_document_session_.insert(&doc, doc_session);
   }
   return *doc_session;
diff --git a/third_party/blink/renderer/core/content_capture/task_session.h b/third_party/blink/renderer/core/content_capture/task_session.h
index 9bf580e..93b5fb7 100644
--- a/third_party/blink/renderer/core/content_capture/task_session.h
+++ b/third_party/blink/renderer/core/content_capture/task_session.h
@@ -22,7 +22,6 @@
 namespace blink {
 
 class Document;
-class SentNodes;
 
 // This class wraps the captured content and the detached nodes that need to be
 // sent out by the ContentCaptureTask, it has a Document to DocumentSession
@@ -51,7 +50,7 @@
     using SentNodeCountCallback = base::RepeatingCallback<void(size_t)>;
 
     DocumentSession(const Document& document,
-                    SentNodes& sent_nodes,
+                    HeapHashSet<WeakMember<const Node>>& sent_nodes,
                     SentNodeCountCallback& call_back);
     ~DocumentSession();
     void AddCapturedNode(Node& node, const gfx::Rect& rect);
@@ -90,7 +89,7 @@
     // LayoutTree.
     WebVector<int64_t> detached_nodes_;
     WeakMember<const Document> document_;
-    Member<SentNodes> sent_nodes_;
+    HeapHashSet<WeakMember<const Node>>* sent_nodes_;
     // The list of changed nodes that needs to be sent.
     HeapHashMap<WeakMember<Node>, gfx::Rect> changed_content_;
 
@@ -102,7 +101,7 @@
     base::Optional<SentNodeCountCallback> callback_;
   };
 
-  TaskSession(SentNodes& sent_nodes);
+  TaskSession();
 
   // Returns the DocumentSession that hasn't been sent.
   DocumentSession* GetNextUnsentDocumentSession();
@@ -132,7 +131,8 @@
   DocumentSession& EnsureDocumentSession(const Document& doc);
   DocumentSession* GetDocumentSession(const Document& document) const;
 
-  Member<SentNodes> sent_nodes_;
+  // A set of weak reference of the node that has been sent.
+  HeapHashSet<WeakMember<const Node>> sent_nodes_;
 
   // The list of node whose value has changed.
   HeapHashSet<WeakMember<Node>> changed_nodes_;
diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.cc b/third_party/blink/renderer/core/exported/web_settings_impl.cc
index abb9aaf..d9ddad03 100644
--- a/third_party/blink/renderer/core/exported/web_settings_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_settings_impl.cc
@@ -133,7 +133,7 @@
   settings_->SetMinimumLogicalFontSize(size);
 }
 
-void WebSettingsImpl::SetAutoplayPolicy(web_pref::AutoplayPolicy policy) {
+void WebSettingsImpl::SetAutoplayPolicy(mojom::blink::AutoplayPolicy policy) {
   settings_->SetAutoplayPolicy(
       static_cast<blink::AutoplayPolicy::Type>(policy));
 }
diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.h b/third_party/blink/renderer/core/exported/web_settings_impl.h
index e7f1017..50d2bfbc 100644
--- a/third_party/blink/renderer/core/exported/web_settings_impl.h
+++ b/third_party/blink/renderer/core/exported/web_settings_impl.h
@@ -52,7 +52,7 @@
   bool ShrinksViewportContentToFit() const override;
   bool ViewportEnabled() const override;
   void SetAccelerated2dCanvasMSAASampleCount(int) override;
-  void SetAutoplayPolicy(web_pref::AutoplayPolicy) override;
+  void SetAutoplayPolicy(mojom::blink::AutoplayPolicy) override;
   void SetPreferCompositingToLCDTextEnabled(bool) override;
   void SetAccessibilityPasswordValuesEnabled(bool) override;
   void SetAllowFileAccessFromFileURLs(bool) override;
diff --git a/third_party/blink/renderer/core/html/forms/radio_input_type.cc b/third_party/blink/renderer/core/html/forms/radio_input_type.cc
index 1f9436a5..c8b4880e 100644
--- a/third_party/blink/renderer/core/html/forms/radio_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/radio_input_type.cc
@@ -165,18 +165,22 @@
 }
 
 void RadioInputType::HandleKeyupEvent(KeyboardEvent& event) {
-  // If an unselected radio is tabbed into (because the entire group has nothing
-  // checked, or because of some explicit .focus() call), then allow space to
-  // check it.
-  if (GetElement().checked())
-    return;
-
   // Use Space key simulated click by default.
   // Use Enter key simulated click when Spatial Navigation enabled.
   if (event.key() == " " ||
       (IsSpatialNavigationEnabled(GetElement().GetDocument().GetFrame()) &&
        event.key() == "Enter")) {
-    DispatchSimulatedClickIfActive(event);
+    // If an unselected radio is tabbed into (because the entire group has
+    // nothing checked, or because of some explicit .focus() call), then allow
+    // space to check it.
+    if (GetElement().checked()) {
+      // If we are going to skip DispatchSimulatedClick, then at least call
+      // SetActive(false) to prevent the radio from being stuck in the active
+      // state.
+      GetElement().SetActive(false);
+    } else {
+      DispatchSimulatedClickIfActive(event);
+    }
   }
 }
 
diff --git a/third_party/blink/renderer/core/html/forms/resources/color_picker.js b/third_party/blink/renderer/core/html/forms/resources/color_picker.js
index 27a78541..cdb678b 100644
--- a/third_party/blink/renderer/core/html/forms/resources/color_picker.js
+++ b/third_party/blink/renderer/core/html/forms/resources/color_picker.js
@@ -4,6 +4,8 @@
 
 /**
  * @fileoverview Color picker used by <input type='color' />
+ *
+ * This can be debugged with manual_tests/forms/color-suggestion-picker.html
  */
 
 function initializeColorPicker() {
diff --git a/third_party/blink/renderer/core/html/media/autoplay_policy.cc b/third_party/blink/renderer/core/html/media/autoplay_policy.cc
index 8ae33d3..40a3873 100644
--- a/third_party/blink/renderer/core/html/media/autoplay_policy.cc
+++ b/third_party/blink/renderer/core/html/media/autoplay_policy.cc
@@ -7,6 +7,7 @@
 #include "build/build_config.h"
 #include "third_party/blink/public/mojom/autoplay/autoplay.mojom-blink.h"
 #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
+#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink.h"
 #include "third_party/blink/public/platform/web_media_player.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_local_frame_client.h"
@@ -395,11 +396,12 @@
   visitor->Trace(autoplay_uma_helper_);
 }
 
-STATIC_ASSERT_ENUM(web_pref::AutoplayPolicy::kNoUserGestureRequired,
+STATIC_ASSERT_ENUM(mojom::blink::AutoplayPolicy::kNoUserGestureRequired,
                    AutoplayPolicy::Type::kNoUserGestureRequired);
-STATIC_ASSERT_ENUM(web_pref::AutoplayPolicy::kUserGestureRequired,
+STATIC_ASSERT_ENUM(mojom::blink::AutoplayPolicy::kUserGestureRequired,
                    AutoplayPolicy::Type::kUserGestureRequired);
-STATIC_ASSERT_ENUM(web_pref::AutoplayPolicy::kDocumentUserActivationRequired,
-                   AutoplayPolicy::Type::kDocumentUserActivationRequired);
+STATIC_ASSERT_ENUM(
+    mojom::blink::AutoplayPolicy::kDocumentUserActivationRequired,
+    AutoplayPolicy::Type::kDocumentUserActivationRequired);
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc b/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
index 8232b5bf..51b1214 100644
--- a/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
+++ b/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
@@ -6,6 +6,7 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/frame/fullscreen.mojom-blink.h"
+#include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
@@ -71,7 +72,7 @@
     frame_host_.Init(
         web_frame_client_.GetRemoteNavigationAssociatedInterfaces());
     GetWebView()->GetSettings()->SetAutoplayPolicy(
-        web_pref::AutoplayPolicy::kUserGestureRequired);
+        mojom::AutoplayPolicy::kUserGestureRequired);
 
     frame_test_helpers::LoadFrame(
         web_view_helper_.GetWebView()->MainFrameImpl(), "about:blank");
diff --git a/third_party/blink/renderer/core/html/resources/html.css b/third_party/blink/renderer/core/html/resources/html.css
index 2ba00720..60762b2 100644
--- a/third_party/blink/renderer/core/html/resources/html.css
+++ b/third_party/blink/renderer/core/html/resources/html.css
@@ -501,6 +501,7 @@
     -webkit-appearance: textarea; /* AutoAppearanceFor() should match to this. */
     background-color: -internal-light-dark(white, black);
     border: 1px solid;
+    column-count: initial !important;
     -webkit-rtl-ordering: logical;
     flex-direction: column;
     resize: auto;
diff --git a/third_party/blink/renderer/core/html/shadow/shadow_element_utils.cc b/third_party/blink/renderer/core/html/shadow/shadow_element_utils.cc
index 5a288fe6..27b11ad 100644
--- a/third_party/blink/renderer/core/html/shadow/shadow_element_utils.cc
+++ b/third_party/blink/renderer/core/html/shadow/shadow_element_utils.cc
@@ -6,6 +6,7 @@
 
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
 #include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
 
 namespace blink {
@@ -27,4 +28,13 @@
          shadow_pseudo == shadow_element_names::kPseudoSliderThumb;
 }
 
+bool IsTextControlPlaceholder(const Node* node) {
+  const auto* element = DynamicTo<Element>(node);
+  if (!element || !element->IsInUserAgentShadowRoot())
+    return false;
+  if (!IsTextControl(element->OwnerShadowHost()))
+    return false;
+  return element->GetIdAttribute() == shadow_element_names::kIdPlaceholder;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/shadow/shadow_element_utils.h b/third_party/blink/renderer/core/html/shadow/shadow_element_utils.h
index 9017ff25..8be2813 100644
--- a/third_party/blink/renderer/core/html/shadow/shadow_element_utils.h
+++ b/third_party/blink/renderer/core/html/shadow/shadow_element_utils.h
@@ -12,6 +12,7 @@
 
 bool IsSliderContainer(const Element& elmenet);
 bool IsSliderThumb(const Node* node);
+bool IsTextControlPlaceholder(const Node* node);
 
 }  // namespace blink
 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_SHADOW_SHADOW_ELEMENT_UTILS_H_
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index d7baf0e..6d14ad22 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -230,7 +230,8 @@
     // We don't check IsRubyText() here intentionally. RubyText width should
     // affect this width.
     if (child.IsOutOfFlowPositioned() ||
-        (child.IsColumnSpanAll() && ConstraintSpace().IsInColumnBfc()))
+        (child.IsColumnSpanAll() && ConstraintSpace().IsInColumnBfc()) ||
+        child.IsTextControlPlaceholder())
       continue;
 
     const ComputedStyle& child_style = child.Style();
@@ -632,6 +633,9 @@
       break;
     } else if (IsRubyText(child)) {
       ruby_text_child = child;
+    } else if (child.IsTextControlPlaceholder()) {
+      HandleTextControlPlaceholder(To<NGBlockNode>(child),
+                                   previous_inflow_position);
     } else {
       // If this is the child we had previously determined to break before, do
       // so now and finish layout.
@@ -2856,6 +2860,24 @@
     PropagateBaselineFromChild(ruby_text_fragment, ruby_text_box_top);
 }
 
+void NGBlockLayoutAlgorithm::HandleTextControlPlaceholder(
+    NGBlockNode placeholder,
+    const NGPreviousInflowPosition& previous_inflow_position) {
+  DCHECK(Node().IsTextControl()) << Node().GetLayoutBox();
+
+  const bool is_new_fc = placeholder.CreatesNewFormattingContext();
+  const NGConstraintSpace space = CreateConstraintSpaceForChild(
+      placeholder,
+      ComputeChildData(previous_inflow_position, placeholder,
+                       /* child_break_token */ nullptr, is_new_fc),
+      ChildAvailableSize(), is_new_fc);
+
+  scoped_refptr<const NGLayoutResult> result = placeholder.Layout(space);
+  container_builder_.AddResult(*result, BorderScrollbarPadding().StartOffset());
+  // This function doesn't update previous_inflow_position. Other children in
+  // this container should ignore |placeholder|.
+}
+
 LogicalOffset NGBlockLayoutAlgorithm::AdjustSliderThumbInlineOffset(
     const NGFragment& fragment,
     const LogicalOffset& logical_offset) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
index 29020eaf..62a1601 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
@@ -343,6 +343,12 @@
   // |ruby_text_child|. This is called only if IsRubyText() returns true.
   void LayoutRubyText(NGLayoutInputNode* ruby_text_child);
 
+  // Layout |placeholder| content, and decide the location of |placeholder|.
+  // This is called only if |this| is a text control.
+  void HandleTextControlPlaceholder(
+      NGBlockNode placeholder,
+      const NGPreviousInflowPosition& previous_inflow_position);
+
   // Adjusts the inline offset of the slider thumb box from the value of
   // HTMLInputElement.
   LogicalOffset AdjustSliderThumbInlineOffset(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc
index 8b5840f..7c85e3a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc
@@ -95,6 +95,10 @@
   return To<LayoutNGTableCell>(box_)->ComputedRowSpan();
 }
 
+bool NGLayoutInputNode::IsTextControlPlaceholder() const {
+  return IsBlock() && blink::IsTextControlPlaceholder(GetDOMNode());
+}
+
 MinMaxSizesResult NGLayoutInputNode::ComputeMinMaxSizes(
     WritingMode writing_mode,
     const MinMaxSizesInput& input,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
index efebd23..83a151d 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
@@ -162,6 +162,7 @@
 
   bool IsTextArea() const { return box_->IsTextAreaIncludingNG(); }
   bool IsTextControl() const { return box_->IsTextControlIncludingNG(); }
+  bool IsTextControlPlaceholder() const;
 
   bool IsMathRoot() const { return box_->IsMathMLRoot(); }
   bool IsMathML() const { return box_->IsMathML(); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_block.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_block.cc
index f5cf0bbc..057b02b 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_block.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_block.cc
@@ -126,14 +126,11 @@
       SetNeedsTransformUpdate();
   }
 
-  if (IsBlendingAllowed()) {
-    bool has_blend_mode_changed =
-        (old_style && old_style->HasBlendMode()) == !StyleRef().HasBlendMode();
-    if (Parent() && has_blend_mode_changed) {
-      Parent()->DescendantIsolationRequirementsChanged(
-          StyleRef().HasBlendMode() ? kDescendantIsolationRequired
-                                    : kDescendantIsolationNeedsUpdate);
-    }
+  if (diff.BlendModeChanged() && Parent()) {
+    DCHECK(IsBlendingAllowed());
+    Parent()->DescendantIsolationRequirementsChanged(
+        StyleRef().HasBlendMode() ? kDescendantIsolationRequired
+                                  : kDescendantIsolationNeedsUpdate);
   }
 
   if (diff.CompositingReasonsChanged())
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
index b53d6fed..60382689 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
@@ -154,17 +154,11 @@
       SetNeedsTransformUpdate();
   }
 
-  if (IsBlendingAllowed()) {
-    bool has_blend_mode_changed =
-        (old_style && old_style->HasBlendMode()) == !StyleRef().HasBlendMode();
-    if (Parent() && has_blend_mode_changed) {
-      Parent()->DescendantIsolationRequirementsChanged(
-          StyleRef().HasBlendMode() ? kDescendantIsolationRequired
-                                    : kDescendantIsolationNeedsUpdate);
-    }
-
-    if (has_blend_mode_changed)
-      SetNeedsPaintPropertyUpdate();
+  if (diff.BlendModeChanged() && Parent() && !IsSVGHiddenContainer()) {
+    DCHECK(IsBlendingAllowed());
+    Parent()->DescendantIsolationRequirementsChanged(
+        StyleRef().HasBlendMode() ? kDescendantIsolationRequired
+                                  : kDescendantIsolationNeedsUpdate);
   }
 
   if (diff.CompositingReasonsChanged())
diff --git a/third_party/blink/renderer/core/testing/origin_trials_test.idl b/third_party/blink/renderer/core/testing/origin_trials_test.idl
index ccb94b74..7d5731c3 100644
--- a/third_party/blink/renderer/core/testing/origin_trials_test.idl
+++ b/third_party/blink/renderer/core/testing/origin_trials_test.idl
@@ -7,7 +7,6 @@
     [RuntimeEnabled=OriginTrialsSampleAPI] static readonly attribute boolean staticAttribute;
     [RuntimeEnabled=OriginTrialsSampleAPI] boolean normalMethod();
     [RuntimeEnabled=OriginTrialsSampleAPI] static boolean staticMethod();
-    [RuntimeEnabled=OriginTrialsSampleAPI] const unsigned short CONSTANT = 1;
 
     // This attribute uses native code to test whether the trial is enabled,
     // and throws an exception in JavaScript if it is not.
@@ -27,7 +26,6 @@
     boolean unconditionalMethod();
     void unconditionalDictionaryMethod(OriginTrialsTestDictionary dict);
     static boolean staticUnconditionalMethod();
-    const unsigned short UNCONDITIONAL_CONSTANT = 99;
 
     // These are available whether or not the trial is enabled, but only in a
     // secure context.
diff --git a/third_party/blink/renderer/core/testing/origin_trials_test_partial.idl b/third_party/blink/renderer/core/testing/origin_trials_test_partial.idl
index fc39c78..49edb8a8 100644
--- a/third_party/blink/renderer/core/testing/origin_trials_test_partial.idl
+++ b/third_party/blink/renderer/core/testing/origin_trials_test_partial.idl
@@ -6,7 +6,6 @@
     ImplementedAs=OriginTrialsTestPartial,
     RuntimeEnabled=OriginTrialsSampleAPI
 ] partial interface OriginTrialsTest {
-    const unsigned short CONSTANT_PARTIAL = 2;
     readonly attribute boolean normalAttributePartial;
     static readonly attribute boolean staticAttributePartial;
     boolean normalMethodPartial();
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
index 4f0c789..6b2192f 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -1120,7 +1120,7 @@
       }
     }
 
-    MarkAXObjectDirty(obj, /*subtree=*/false);
+    PostNotification(obj, ax::mojom::Event::kTextChanged);
   }
 
   if (optional_node_for_relation_update)
diff --git a/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc b/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc
index aecb4f8..36480b9 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc
@@ -294,7 +294,7 @@
     GetReverseRelated(node, related_sources);
     for (AXObject* related : related_sources) {
       if (related)
-        object_cache_->MarkAXObjectDirty(related, /*subtree=*/false);
+        TextChanged(related);
     }
 
     // Forward relation via <label for="[id]">.
@@ -331,6 +331,10 @@
   object->ChildrenChanged();
 }
 
+void AXRelationCache::TextChanged(AXObject* object) {
+  object_cache_->PostNotification(object, ax::mojom::Event::kTextChanged);
+}
+
 void AXRelationCache::LabelChanged(Node* node) {
   const auto& id =
       To<HTMLElement>(node)->FastGetAttribute(html_names::kForAttr);
@@ -338,7 +342,7 @@
     all_previously_seen_label_target_ids_.insert(id);
     if (auto* control = To<HTMLLabelElement>(node)->control()) {
       if (AXObject* obj = Get(control))
-        object_cache_->MarkAXObjectDirty(obj, /*subtree=*/false);
+        TextChanged(obj);
     }
   }
 }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h b/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h
index 6833bca..591ffc9d 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h
@@ -126,6 +126,7 @@
   AXObject* GetOrCreate(Node*);
   AXObject* Get(Node*);
   void ChildrenChanged(AXObject*);
+  void TextChanged(AXObject*);
 
   DISALLOW_COPY_AND_ASSIGN(AXRelationCache);
 };
diff --git a/third_party/blink/renderer/modules/virtualkeyboard/idls.gni b/third_party/blink/renderer/modules/virtualkeyboard/idls.gni
index 2f8c334a..8f0c014 100644
--- a/third_party/blink/renderer/modules/virtualkeyboard/idls.gni
+++ b/third_party/blink/renderer/modules/virtualkeyboard/idls.gni
@@ -7,7 +7,4 @@
   "virtual_keyboard_geometry_change_event.idl",
 ]
 
-modules_dictionary_idl_files =
-    [ "virtual_keyboard_geometry_change_event_init.idl" ]
-
 modules_dependency_idl_files = [ "navigator_virtual_keyboard.idl" ]
diff --git a/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.cc b/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.cc
index c2681ad..2d74fa0 100644
--- a/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.cc
+++ b/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard.cc
@@ -85,7 +85,7 @@
         StyleEnvironmentVariables::FormatPx(keyboard_rect.height()));
   }
   DispatchEvent(*(MakeGarbageCollected<VirtualKeyboardGeometryChangeEvent>(
-      event_type_names::kGeometrychange, bounding_rect_)));
+      event_type_names::kGeometrychange)));
 }
 
 void VirtualKeyboard::show() {
diff --git a/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.cc b/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.cc
index 22ddffb..6c44834 100644
--- a/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.cc
+++ b/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.cc
@@ -4,31 +4,15 @@
 
 #include "third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.h"
 
-#include "third_party/blink/renderer/bindings/modules/v8/v8_virtual_keyboard_geometry_change_event_init.h"
-#include "third_party/blink/renderer/core/geometry/dom_rect.h"
-
 namespace blink {
 
 VirtualKeyboardGeometryChangeEvent* VirtualKeyboardGeometryChangeEvent::Create(
-    const AtomicString& type,
-    const VirtualKeyboardGeometryChangeEventInit* initializer) {
-  return MakeGarbageCollected<VirtualKeyboardGeometryChangeEvent>(type,
-                                                                  initializer);
+    const AtomicString& type) {
+  return MakeGarbageCollected<VirtualKeyboardGeometryChangeEvent>(type);
 }
 
 VirtualKeyboardGeometryChangeEvent::VirtualKeyboardGeometryChangeEvent(
-    const AtomicString& type,
-    const VirtualKeyboardGeometryChangeEventInit* initializer)
-    : Event(type, initializer) {}
-
-VirtualKeyboardGeometryChangeEvent::VirtualKeyboardGeometryChangeEvent(
-    const AtomicString& type,
-    DOMRect* rect)
-    : Event(type, Bubbles::kNo, Cancelable::kNo), bounding_rect_(rect) {}
-
-void VirtualKeyboardGeometryChangeEvent::Trace(Visitor* visitor) const {
-  visitor->Trace(bounding_rect_);
-  Event::Trace(visitor);
-}
+    const AtomicString& type)
+    : Event(type, Bubbles::kNo, Cancelable::kNo) {}
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.h b/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.h
index 9aa2ab6..01a44a7 100644
--- a/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.h
+++ b/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.h
@@ -10,28 +10,13 @@
 
 namespace blink {
 
-class DOMRect;
-class VirtualKeyboardGeometryChangeEventInit;
-
 class VirtualKeyboardGeometryChangeEvent final : public Event {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static VirtualKeyboardGeometryChangeEvent* Create(
-      const AtomicString& type,
-      const VirtualKeyboardGeometryChangeEventInit*);
+  static VirtualKeyboardGeometryChangeEvent* Create(const AtomicString& type);
 
-  VirtualKeyboardGeometryChangeEvent(
-      const AtomicString& type,
-      const VirtualKeyboardGeometryChangeEventInit*);
-  VirtualKeyboardGeometryChangeEvent(const AtomicString& type, DOMRect*);
-
-  DOMRect* boundingRect() const { return bounding_rect_; }
-
-  void Trace(Visitor*) const override;
-
- private:
-  Member<DOMRect> bounding_rect_;
+  explicit VirtualKeyboardGeometryChangeEvent(const AtomicString& type);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.idl b/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.idl
index 5275936..be91aa89 100644
--- a/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.idl
+++ b/third_party/blink/renderer/modules/virtualkeyboard/virtual_keyboard_geometry_change_event.idl
@@ -10,7 +10,6 @@
     Exposed=Window,
     RuntimeEnabled=VirtualKeyboard
 ] interface VirtualKeyboardGeometryChangeEvent : Event {
-    constructor(DOMString type, VirtualKeyboardGeometryChangeEventInit eventInitDict);
-    [SameObject] readonly attribute DOMRect boundingRect;
+    constructor(DOMString type);
 };
 
diff --git a/third_party/blink/renderer/modules/xr/xr_session.cc b/third_party/blink/renderer/modules/xr/xr_session.cc
index 82eb49b..644a1e0 100644
--- a/third_party/blink/renderer/modules/xr/xr_session.cc
+++ b/third_party/blink/renderer/modules/xr/xr_session.cc
@@ -307,8 +307,8 @@
     mojo::PendingReceiver<device::mojom::blink::XRSessionClient>
         client_receiver,
     device::mojom::blink::XRSessionMode mode,
-    device::mojom::blink::XREnvironmentBlendMode environment_blend_mode,
-    device::mojom::blink::XRInteractionMode interaction_mode,
+    EnvironmentBlendMode environment_blend_mode,
+    InteractionMode interaction_mode,
     device::mojom::blink::XRSessionDeviceConfigPtr device_config,
     bool sensorless_session,
     XRSessionFeatureSet enabled_features)
@@ -346,13 +346,13 @@
            << ": supports_viewport_scaling_=" << supports_viewport_scaling_;
 
   switch (environment_blend_mode) {
-    case device::mojom::blink::XREnvironmentBlendMode::kOpaque:
+    case kBlendModeOpaque:
       blend_mode_string_ = "opaque";
       break;
-    case device::mojom::blink::XREnvironmentBlendMode::kAdditive:
+    case kBlendModeAdditive:
       blend_mode_string_ = "additive";
       break;
-    case device::mojom::blink::XREnvironmentBlendMode::kAlphaBlend:
+    case kBlendModeAlphaBlend:
       blend_mode_string_ = "alpha-blend";
       break;
     default:
@@ -361,10 +361,10 @@
   }
 
   switch (interaction_mode) {
-    case device::mojom::blink::XRInteractionMode::kScreenSpace:
+    case kInteractionModeScreen:
       interaction_mode_string_ = "screen-space";
       break;
-    case device::mojom::blink::XRInteractionMode::kWorldSpace:
+    case kInteractionModeWorld:
       interaction_mode_string_ = "world-space";
       break;
   }
diff --git a/third_party/blink/renderer/modules/xr/xr_session.h b/third_party/blink/renderer/modules/xr/xr_session.h
index 59a0d670..476e365 100644
--- a/third_party/blink/renderer/modules/xr/xr_session.h
+++ b/third_party/blink/renderer/modules/xr/xr_session.h
@@ -86,6 +86,14 @@
   // they are run in the same turn of the render loop.
   using ExecuteVfcCallback = base::OnceCallback<void(double)>;
 
+  enum EnvironmentBlendMode {
+    kBlendModeOpaque = 0,
+    kBlendModeAdditive,
+    kBlendModeAlphaBlend
+  };
+
+  enum InteractionMode { kInteractionModeScreen = 0, kInteractionModeWorld };
+
   struct MetricsReporter {
     explicit MetricsReporter(
         mojo::Remote<device::mojom::blink::XRSessionMetricsRecorder> recorder);
@@ -106,8 +114,8 @@
             mojo::PendingReceiver<device::mojom::blink::XRSessionClient>
                 client_receiver,
             device::mojom::blink::XRSessionMode mode,
-            device::mojom::blink::XREnvironmentBlendMode environment_blend_mode,
-            device::mojom::blink::XRInteractionMode interaction_mode,
+            EnvironmentBlendMode environment_blend_mode,
+            InteractionMode interaction_mode,
             device::mojom::blink::XRSessionDeviceConfigPtr device_config,
             bool sensorless_session,
             XRSessionFeatureSet enabled_features);
diff --git a/third_party/blink/renderer/modules/xr/xr_system.cc b/third_party/blink/renderer/modules/xr/xr_system.cc
index f662d7b..e2b6dc4c 100644
--- a/third_party/blink/renderer/modules/xr/xr_system.cc
+++ b/third_party/blink/renderer/modules/xr/xr_system.cc
@@ -1403,17 +1403,31 @@
   DVLOG(2) << __func__
            << ": environment_integration=" << environment_integration;
 
+  // TODO(https://crbug.com/944936): The blend mode could be "additive".
+  XRSession::EnvironmentBlendMode blend_mode = XRSession::kBlendModeOpaque;
+  if (environment_integration)
+    blend_mode = XRSession::kBlendModeAlphaBlend;
+
+  // TODO(https://crbug.com/1069350): The runtime should be the one to
+  // communicate the interaction mode, but for the moment we're going to use
+  // session mode and assume all AR is phone AR.
+  XRSession::InteractionMode interaction_mode =
+      XRSession::kInteractionModeWorld;
+  if (query->mode() == device::mojom::blink::XRSessionMode::kInline ||
+      query->mode() == device::mojom::blink::XRSessionMode::kImmersiveAr)
+    interaction_mode = XRSession::kInteractionModeScreen;
+
   XRSessionFeatureSet enabled_features;
   for (const auto& feature : session_ptr->enabled_features) {
     DVLOG(2) << __func__ << ": feature " << feature << " will be enabled";
     enabled_features.insert(feature);
   }
 
-  XRSession* session = CreateSession(
-      query->mode(), session_ptr->enviroment_blend_mode,
-      session_ptr->interaction_mode, std::move(session_ptr->client_receiver),
-      std::move(session_ptr->display_info),
-      std::move(session_ptr->device_config), enabled_features);
+  XRSession* session =
+      CreateSession(query->mode(), blend_mode, interaction_mode,
+                    std::move(session_ptr->client_receiver),
+                    std::move(session_ptr->display_info),
+                    std::move(session_ptr->device_config), enabled_features);
 
   frameProvider()->OnSessionStarted(session, std::move(session_ptr));
 
@@ -1512,8 +1526,8 @@
 // A session is always created and returned.
 XRSession* XRSystem::CreateSession(
     device::mojom::blink::XRSessionMode mode,
-    device::mojom::blink::XREnvironmentBlendMode blend_mode,
-    device::mojom::blink::XRInteractionMode interaction_mode,
+    XRSession::EnvironmentBlendMode blend_mode,
+    XRSession::InteractionMode interaction_mode,
     mojo::PendingReceiver<device::mojom::blink::XRSessionClient>
         client_receiver,
     device::mojom::blink::VRDisplayInfoPtr display_info,
@@ -1532,10 +1546,9 @@
 
 XRSession* XRSystem::CreateSensorlessInlineSession() {
   // TODO(https://crbug.com/944936): The blend mode could be "additive".
-  device::mojom::blink::XREnvironmentBlendMode blend_mode =
-      device::mojom::blink::XREnvironmentBlendMode::kOpaque;
-  device::mojom::blink::XRInteractionMode interaction_mode =
-      device::mojom::blink::XRInteractionMode::kScreenSpace;
+  XRSession::EnvironmentBlendMode blend_mode = XRSession::kBlendModeOpaque;
+  XRSession::InteractionMode interaction_mode =
+      XRSession::kInteractionModeScreen;
   device::mojom::blink::XRSessionDeviceConfigPtr device_config =
       device::mojom::blink::XRSessionDeviceConfig::New();
   return CreateSession(device::mojom::blink::XRSessionMode::kInline, blend_mode,
diff --git a/third_party/blink/renderer/modules/xr/xr_system.h b/third_party/blink/renderer/modules/xr/xr_system.h
index a9a71a1..c4f76fa 100644
--- a/third_party/blink/renderer/modules/xr/xr_system.h
+++ b/third_party/blink/renderer/modules/xr/xr_system.h
@@ -388,8 +388,8 @@
 
   XRSession* CreateSession(
       device::mojom::blink::XRSessionMode mode,
-      device::mojom::blink::XREnvironmentBlendMode blend_mode,
-      device::mojom::blink::XRInteractionMode interaction_mode,
+      XRSession::EnvironmentBlendMode blend_mode,
+      XRSession::InteractionMode interaction_mode,
       mojo::PendingReceiver<device::mojom::blink::XRSessionClient>
           client_receiver,
       device::mojom::blink::VRDisplayInfoPtr display_info,
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 207fe39..37feef0 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -418,6 +418,8 @@
     "bindings/exception_messages.h",
     "bindings/exception_state.cc",
     "bindings/exception_state.h",
+    "bindings/idl_member_installer.cc",
+    "bindings/idl_member_installer.h",
     "bindings/microtask.cc",
     "bindings/microtask.h",
     "bindings/name_client.h",
diff --git a/third_party/blink/renderer/platform/bindings/idl_member_installer.cc b/third_party/blink/renderer/platform/bindings/idl_member_installer.cc
new file mode 100644
index 0000000..520ff5d
--- /dev/null
+++ b/third_party/blink/renderer/platform/bindings/idl_member_installer.cc
@@ -0,0 +1,553 @@
+// 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/platform/bindings/idl_member_installer.h"
+
+#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
+#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
+#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
+
+namespace blink {
+
+namespace bindings {
+
+namespace {
+
+template <typename Config>
+bool DoesWorldMatch(const Config& config, const DOMWrapperWorld& world) {
+  const unsigned world_bit = static_cast<unsigned>(
+      world.IsMainWorld() ? IDLMemberInstaller::FlagWorld::kMainWorld
+                          : IDLMemberInstaller::FlagWorld::kNonMainWorlds);
+  return config.world & world_bit;
+}
+
+enum class FunctionKind {
+  kAttributeGet,
+  kAttributeSet,
+  kOperation,
+};
+
+template <FunctionKind kind, typename Config>
+v8::FunctionCallback GetConfigCallback(const Config& config);
+template <>
+v8::FunctionCallback GetConfigCallback<FunctionKind::kAttributeGet>(
+    const IDLMemberInstaller::AttributeConfig& config) {
+  return config.callback_for_get;
+}
+template <>
+v8::FunctionCallback GetConfigCallback<FunctionKind::kAttributeSet>(
+    const IDLMemberInstaller::AttributeConfig& config) {
+  return config.callback_for_set;
+}
+template <>
+v8::FunctionCallback GetConfigCallback<FunctionKind::kOperation>(
+    const IDLMemberInstaller::OperationConfig& config) {
+  return config.callback;
+}
+
+template <FunctionKind kind, typename Config>
+int GetConfigLength(const Config& config);
+template <>
+int GetConfigLength<FunctionKind::kAttributeGet>(
+    const IDLMemberInstaller::AttributeConfig& config) {
+  return 0;
+}
+template <>
+int GetConfigLength<FunctionKind::kAttributeSet>(
+    const IDLMemberInstaller::AttributeConfig& config) {
+  return 1;
+}
+template <>
+int GetConfigLength<FunctionKind::kOperation>(
+    const IDLMemberInstaller::OperationConfig& config) {
+  return config.length;
+}
+
+template <FunctionKind kind, typename Config>
+IDLMemberInstaller::FlagCrossOriginCheck GetConfigCrossOriginCheck(
+    const Config& config);
+template <>
+IDLMemberInstaller::FlagCrossOriginCheck
+GetConfigCrossOriginCheck<FunctionKind::kAttributeGet>(
+    const IDLMemberInstaller::AttributeConfig& config) {
+  return static_cast<IDLMemberInstaller::FlagCrossOriginCheck>(
+      config.cross_origin_check_for_get);
+}
+template <>
+IDLMemberInstaller::FlagCrossOriginCheck
+GetConfigCrossOriginCheck<FunctionKind::kAttributeSet>(
+    const IDLMemberInstaller::AttributeConfig& config) {
+  return static_cast<IDLMemberInstaller::FlagCrossOriginCheck>(
+      config.cross_origin_check_for_set);
+}
+template <>
+IDLMemberInstaller::FlagCrossOriginCheck
+GetConfigCrossOriginCheck<FunctionKind::kOperation>(
+    const IDLMemberInstaller::OperationConfig& config) {
+  return static_cast<IDLMemberInstaller::FlagCrossOriginCheck>(
+      config.cross_origin_check);
+}
+
+template <FunctionKind kind, typename Config>
+v8::SideEffectType GetConfigSideEffect(const Config& config);
+template <>
+v8::SideEffectType GetConfigSideEffect<FunctionKind::kAttributeGet>(
+    const IDLMemberInstaller::AttributeConfig& config) {
+  return static_cast<v8::SideEffectType>(config.v8_side_effect);
+}
+template <>
+v8::SideEffectType GetConfigSideEffect<FunctionKind::kAttributeSet>(
+    const IDLMemberInstaller::AttributeConfig& config) {
+  return v8::SideEffectType::kHasSideEffect;
+}
+template <>
+v8::SideEffectType GetConfigSideEffect<FunctionKind::kOperation>(
+    const IDLMemberInstaller::OperationConfig& config) {
+  return static_cast<v8::SideEffectType>(config.v8_side_effect);
+}
+
+template <FunctionKind kind, typename Config>
+V8PrivateProperty::CachedAccessor GetConfigV8CachedAccessor(
+    const Config& config);
+template <>
+V8PrivateProperty::CachedAccessor
+GetConfigV8CachedAccessor<FunctionKind::kAttributeGet>(
+    const IDLMemberInstaller::AttributeConfig& config) {
+  return static_cast<V8PrivateProperty::CachedAccessor>(
+      config.v8_cached_accessor);
+}
+template <>
+V8PrivateProperty::CachedAccessor
+GetConfigV8CachedAccessor<FunctionKind::kAttributeSet>(
+    const IDLMemberInstaller::AttributeConfig& config) {
+  return V8PrivateProperty::CachedAccessor::kNone;
+}
+template <>
+V8PrivateProperty::CachedAccessor
+GetConfigV8CachedAccessor<FunctionKind::kOperation>(
+    const IDLMemberInstaller::OperationConfig& config) {
+  return V8PrivateProperty::CachedAccessor::kNone;
+}
+
+template <FunctionKind kind, typename Config>
+v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
+    v8::Isolate* isolate,
+    const DOMWrapperWorld& world,
+    v8::Local<v8::Signature> signature,
+    v8::Local<v8::String> name,
+    const Config& config,
+    const v8::CFunction* v8_c_function = nullptr) {
+  v8::FunctionCallback callback = GetConfigCallback<kind>(config);
+  if (!callback)
+    return v8::Local<v8::FunctionTemplate>();
+
+  int length = GetConfigLength<kind>(config);
+  v8::SideEffectType v8_side_effect = GetConfigSideEffect<kind>(config);
+  V8PrivateProperty::CachedAccessor v8_cached_accessor =
+      GetConfigV8CachedAccessor<kind>(config);
+
+  v8::Local<v8::FunctionTemplate> function_template;
+  if (v8_cached_accessor == V8PrivateProperty::CachedAccessor::kNone ||
+      (v8_cached_accessor ==
+           V8PrivateProperty::CachedAccessor::kWindowDocument &&
+       !world.IsMainWorld())) {
+    function_template = v8::FunctionTemplate::New(
+        isolate, callback, v8::Local<v8::Value>(), signature, length,
+        v8::ConstructorBehavior::kThrow, v8_side_effect, v8_c_function);
+  } else {
+    function_template = v8::FunctionTemplate::NewWithCache(
+        isolate, callback,
+        V8PrivateProperty::GetCachedAccessor(isolate, v8_cached_accessor)
+            .GetPrivate(),
+        v8::Local<v8::Value>(), signature, length, v8_side_effect);
+  }
+
+  function_template->SetClassName(name);
+  function_template->RemovePrototype();
+  function_template->SetAcceptAnyReceiver(
+      GetConfigCrossOriginCheck<kind>(config) ==
+      IDLMemberInstaller::FlagCrossOriginCheck::kDoNotCheck);
+
+  return function_template;
+}
+
+template <FunctionKind kind, typename Config>
+v8::Local<v8::Function> CreateFunction(v8::Isolate* isolate,
+                                       v8::Local<v8::Context> context,
+                                       const DOMWrapperWorld& world,
+                                       v8::Local<v8::Signature> signature,
+                                       v8::Local<v8::String> name,
+                                       const Config& config) {
+  if (!GetConfigCallback<kind>(config))
+    return v8::Local<v8::Function>();
+
+  return CreateFunctionTemplate<kind>(isolate, world, signature, name, config)
+      ->GetFunction(context)
+      .ToLocalChecked();
+}
+
+void InstallAttribute(v8::Isolate* isolate,
+                      const DOMWrapperWorld& world,
+                      v8::Local<v8::Template> instance_template,
+                      v8::Local<v8::Template> prototype_template,
+                      v8::Local<v8::Template> interface_template,
+                      v8::Local<v8::Signature> signature,
+                      const IDLMemberInstaller::AttributeConfig& config) {
+  if (!DoesWorldMatch(config, world))
+    return;
+
+  IDLMemberInstaller::FlagLocation location =
+      static_cast<IDLMemberInstaller::FlagLocation>(config.location);
+  if (static_cast<IDLMemberInstaller::FlagReceiverCheck>(
+          config.receiver_check) ==
+          IDLMemberInstaller::FlagReceiverCheck::kDoNotCheck ||
+      location == IDLMemberInstaller::FlagLocation::kInterface)
+    signature = v8::Local<v8::Signature>();
+
+  StringView name_as_view(config.name);
+  v8::Local<v8::String> name = V8AtomicString(isolate, name_as_view);
+  v8::Local<v8::String> get_name = V8AtomicString(
+      isolate, static_cast<String>(StringView("get ", 4) + name_as_view));
+  v8::Local<v8::String> set_name = V8AtomicString(
+      isolate, static_cast<String>(StringView("set ", 4) + name_as_view));
+  v8::Local<v8::FunctionTemplate> get_func =
+      CreateFunctionTemplate<FunctionKind::kAttributeGet>(
+          isolate, world, signature, get_name, config);
+  v8::Local<v8::FunctionTemplate> set_func =
+      CreateFunctionTemplate<FunctionKind::kAttributeSet>(
+          isolate, world, signature, set_name, config);
+
+  v8::Local<v8::Template> target_template;
+  switch (location) {
+    case IDLMemberInstaller::FlagLocation::kInstance:
+      target_template = instance_template;
+      break;
+    case IDLMemberInstaller::FlagLocation::kPrototype:
+      target_template = prototype_template;
+      break;
+    case IDLMemberInstaller::FlagLocation::kInterface:
+      target_template = interface_template;
+      break;
+    default:
+      NOTREACHED();
+  }
+  target_template->SetAccessorProperty(
+      name, get_func, set_func,
+      static_cast<v8::PropertyAttribute>(config.v8_property_attribute));
+}
+
+void InstallAttribute(v8::Isolate* isolate,
+                      v8::Local<v8::Context> context,
+                      const DOMWrapperWorld& world,
+                      v8::Local<v8::Object> instance_object,
+                      v8::Local<v8::Object> prototype_object,
+                      v8::Local<v8::Object> interface_object,
+                      v8::Local<v8::Signature> signature,
+                      const IDLMemberInstaller::AttributeConfig& config) {
+  if (!DoesWorldMatch(config, world))
+    return;
+
+  IDLMemberInstaller::FlagLocation location =
+      static_cast<IDLMemberInstaller::FlagLocation>(config.location);
+  if (static_cast<IDLMemberInstaller::FlagReceiverCheck>(
+          config.receiver_check) ==
+          IDLMemberInstaller::FlagReceiverCheck::kDoNotCheck ||
+      location == IDLMemberInstaller::FlagLocation::kInterface)
+    signature = v8::Local<v8::Signature>();
+
+  StringView name_as_view(config.name);
+  v8::Local<v8::String> name = V8AtomicString(isolate, name_as_view);
+  v8::Local<v8::String> get_name = V8AtomicString(
+      isolate, static_cast<String>(StringView("get ", 4) + name_as_view));
+  v8::Local<v8::String> set_name = V8AtomicString(
+      isolate, static_cast<String>(StringView("set ", 4) + name_as_view));
+  v8::Local<v8::Function> get_func =
+      CreateFunction<FunctionKind::kAttributeGet>(isolate, context, world,
+                                                  signature, get_name, config);
+  v8::Local<v8::Function> set_func =
+      CreateFunction<FunctionKind::kAttributeSet>(isolate, context, world,
+                                                  signature, set_name, config);
+
+  v8::Local<v8::Object> target_object;
+  switch (location) {
+    case IDLMemberInstaller::FlagLocation::kInstance:
+      target_object = instance_object;
+      break;
+    case IDLMemberInstaller::FlagLocation::kPrototype:
+      target_object = prototype_object;
+      break;
+    case IDLMemberInstaller::FlagLocation::kInterface:
+      target_object = interface_object;
+      break;
+    default:
+      NOTREACHED();
+  }
+  target_object->SetAccessorProperty(
+      name, get_func, set_func,
+      static_cast<v8::PropertyAttribute>(config.v8_property_attribute));
+}
+
+void InstallOperation(v8::Isolate* isolate,
+                      const DOMWrapperWorld& world,
+                      v8::Local<v8::Template> instance_template,
+                      v8::Local<v8::Template> prototype_template,
+                      v8::Local<v8::Template> interface_template,
+                      v8::Local<v8::Signature> signature,
+                      const IDLMemberInstaller::OperationConfig& config,
+                      const v8::CFunction* v8_c_function = nullptr) {
+  if (!DoesWorldMatch(config, world))
+    return;
+
+  IDLMemberInstaller::FlagLocation location =
+      static_cast<IDLMemberInstaller::FlagLocation>(config.location);
+  if (static_cast<IDLMemberInstaller::FlagReceiverCheck>(
+          config.receiver_check) ==
+          IDLMemberInstaller::FlagReceiverCheck::kDoNotCheck ||
+      location == IDLMemberInstaller::FlagLocation::kInterface)
+    signature = v8::Local<v8::Signature>();
+
+  v8::Local<v8::String> name = V8AtomicString(isolate, config.name);
+  v8::Local<v8::FunctionTemplate> func =
+      CreateFunctionTemplate<FunctionKind::kOperation>(
+          isolate, world, signature, name, config, v8_c_function);
+
+  v8::Local<v8::Template> target_template;
+  switch (location) {
+    case IDLMemberInstaller::FlagLocation::kInstance:
+      target_template = instance_template;
+      break;
+    case IDLMemberInstaller::FlagLocation::kPrototype:
+      target_template = prototype_template;
+      break;
+    case IDLMemberInstaller::FlagLocation::kInterface:
+      target_template = interface_template;
+      break;
+    default:
+      NOTREACHED();
+  }
+  target_template->Set(
+      name, func,
+      static_cast<v8::PropertyAttribute>(config.v8_property_attribute));
+}
+
+void InstallOperation(v8::Isolate* isolate,
+                      v8::Local<v8::Context> context,
+                      const DOMWrapperWorld& world,
+                      v8::Local<v8::Object> instance_object,
+                      v8::Local<v8::Object> prototype_object,
+                      v8::Local<v8::Object> interface_object,
+                      v8::Local<v8::Signature> signature,
+                      const IDLMemberInstaller::OperationConfig& config) {
+  if (!DoesWorldMatch(config, world))
+    return;
+
+  IDLMemberInstaller::FlagLocation location =
+      static_cast<IDLMemberInstaller::FlagLocation>(config.location);
+  if (static_cast<IDLMemberInstaller::FlagReceiverCheck>(
+          config.receiver_check) ==
+          IDLMemberInstaller::FlagReceiverCheck::kDoNotCheck ||
+      location == IDLMemberInstaller::FlagLocation::kInterface)
+    signature = v8::Local<v8::Signature>();
+
+  v8::Local<v8::String> name = V8AtomicString(isolate, config.name);
+  v8::Local<v8::Function> func = CreateFunction<FunctionKind::kOperation>(
+      isolate, context, world, signature, name, config);
+
+  v8::Local<v8::Object> target_object;
+  switch (location) {
+    case IDLMemberInstaller::FlagLocation::kInstance:
+      target_object = instance_object;
+      break;
+    case IDLMemberInstaller::FlagLocation::kPrototype:
+      target_object = prototype_object;
+      break;
+    case IDLMemberInstaller::FlagLocation::kInterface:
+      target_object = interface_object;
+      break;
+    default:
+      NOTREACHED();
+  }
+  target_object
+      ->DefineOwnProperty(
+          context, name, func,
+          static_cast<v8::PropertyAttribute>(config.v8_property_attribute))
+      .ToChecked();
+}
+
+}  // namespace
+
+// static
+void IDLMemberInstaller::InstallAttributes(
+    v8::Isolate* isolate,
+    const DOMWrapperWorld& world,
+    v8::Local<v8::Template> instance_template,
+    v8::Local<v8::Template> prototype_template,
+    v8::Local<v8::Template> interface_template,
+    v8::Local<v8::Signature> signature,
+    base::span<const AttributeConfig> configs) {
+  for (const auto& config : configs) {
+    InstallAttribute(isolate, world, instance_template, prototype_template,
+                     interface_template, signature, config);
+  }
+}
+
+// static
+void IDLMemberInstaller::InstallAttributes(
+    v8::Isolate* isolate,
+    const DOMWrapperWorld& world,
+    v8::Local<v8::Object> instance_object,
+    v8::Local<v8::Object> prototype_object,
+    v8::Local<v8::Object> interface_object,
+    v8::Local<v8::Signature> signature,
+    base::span<const AttributeConfig> configs) {
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  for (const auto& config : configs) {
+    InstallAttribute(isolate, context, world, instance_object, prototype_object,
+                     interface_object, signature, config);
+  }
+}
+
+// static
+void IDLMemberInstaller::InstallConstants(
+    v8::Isolate* isolate,
+    const DOMWrapperWorld& world,
+    v8::Local<v8::Template> instance_template,
+    v8::Local<v8::Template> prototype_template,
+    v8::Local<v8::Template> interface_template,
+    v8::Local<v8::Signature> signature,
+    base::span<const ConstantCallbackConfig> configs) {
+  const bool has_prototype_template = !prototype_template.IsEmpty();
+  const v8::PropertyAttribute v8_property_attribute =
+      static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
+  for (const auto& config : configs) {
+    v8::Local<v8::String> name = V8AtomicString(isolate, config.name);
+    if (has_prototype_template) {
+      prototype_template->SetLazyDataProperty(
+          name, config.callback, v8::Local<v8::Value>(), v8_property_attribute,
+          v8::SideEffectType::kHasNoSideEffect);
+    }
+    interface_template->SetLazyDataProperty(
+        name, config.callback, v8::Local<v8::Value>(), v8_property_attribute,
+        v8::SideEffectType::kHasNoSideEffect);
+  }
+}
+
+// static
+void IDLMemberInstaller::InstallConstants(
+    v8::Isolate* isolate,
+    const DOMWrapperWorld& world,
+    v8::Local<v8::Template> instance_template,
+    v8::Local<v8::Template> prototype_template,
+    v8::Local<v8::Template> interface_template,
+    v8::Local<v8::Signature> signature,
+    base::span<const ConstantValueConfig> configs) {
+  const bool has_prototype_template = !prototype_template.IsEmpty();
+  const v8::PropertyAttribute v8_property_attribute =
+      static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
+  for (const auto& config : configs) {
+    v8::Local<v8::String> name = V8AtomicString(isolate, config.name);
+    v8::Local<v8::Integer> value;
+    if (config.value < 0) {
+      int32_t i32_value = static_cast<int32_t>(config.value);
+      DCHECK_EQ(static_cast<int64_t>(i32_value), config.value);
+      value = v8::Integer::New(isolate, i32_value);
+    } else {
+      uint32_t u32_value = static_cast<uint32_t>(config.value);
+      DCHECK_EQ(static_cast<int64_t>(u32_value), config.value);
+      value = v8::Integer::NewFromUnsigned(isolate, u32_value);
+    }
+    if (has_prototype_template) {
+      prototype_template->Set(name, value, v8_property_attribute);
+    }
+    interface_template->Set(name, value, v8_property_attribute);
+  }
+}
+
+// static
+void IDLMemberInstaller::InstallOperations(
+    v8::Isolate* isolate,
+    const DOMWrapperWorld& world,
+    v8::Local<v8::Template> instance_template,
+    v8::Local<v8::Template> prototype_template,
+    v8::Local<v8::Template> interface_template,
+    v8::Local<v8::Signature> signature,
+    base::span<const OperationConfig> configs) {
+  for (const auto& config : configs) {
+    InstallOperation(isolate, world, instance_template, prototype_template,
+                     interface_template, signature, config);
+  }
+}
+
+// static
+void IDLMemberInstaller::InstallOperations(
+    v8::Isolate* isolate,
+    const DOMWrapperWorld& world,
+    v8::Local<v8::Object> instance_object,
+    v8::Local<v8::Object> prototype_object,
+    v8::Local<v8::Object> interface_object,
+    v8::Local<v8::Signature> signature,
+    base::span<const OperationConfig> configs) {
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  for (const auto& config : configs) {
+    InstallOperation(isolate, context, world, instance_object, prototype_object,
+                     interface_object, signature, config);
+  }
+}
+
+// static
+void IDLMemberInstaller::InstallOperations(
+    v8::Isolate* isolate,
+    const DOMWrapperWorld& world,
+    v8::Local<v8::Template> instance_template,
+    v8::Local<v8::Template> prototype_template,
+    v8::Local<v8::Template> interface_template,
+    v8::Local<v8::Signature> signature,
+    base::span<const NoAllocDirectCallOperationConfig> configs) {
+  for (const auto& config : configs) {
+    InstallOperation(isolate, world, instance_template, prototype_template,
+                     interface_template, signature, config.operation_config,
+                     &config.v8_c_function);
+  }
+}
+
+// static
+void IDLMemberInstaller::InstallExposedConstructs(
+    v8::Isolate* isolate,
+    const DOMWrapperWorld& world,
+    v8::Local<v8::Template> instance_template,
+    v8::Local<v8::Template> prototype_template,
+    v8::Local<v8::Template> interface_template,
+    v8::Local<v8::Signature> signature,
+    base::span<const ExposedConstructConfig> configs) {
+  for (const auto& config : configs) {
+    v8::Local<v8::String> name = V8AtomicString(isolate, config.name);
+    instance_template->SetLazyDataProperty(
+        name, config.callback, v8::Local<v8::Value>(), v8::DontEnum,
+        v8::SideEffectType::kHasNoSideEffect);
+  }
+}
+
+// static
+void IDLMemberInstaller::InstallExposedConstructs(
+    v8::Isolate* isolate,
+    const DOMWrapperWorld& world,
+    v8::Local<v8::Object> instance_object,
+    v8::Local<v8::Object> prototype_object,
+    v8::Local<v8::Object> interface_object,
+    v8::Local<v8::Signature> signature,
+    base::span<const ExposedConstructConfig> configs) {
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  for (const auto& config : configs) {
+    instance_object
+        ->SetLazyDataProperty(context, V8AtomicString(isolate, config.name),
+                              config.callback, v8::Local<v8::Value>(),
+                              v8::DontEnum,
+                              v8::SideEffectType::kHasNoSideEffect)
+        .ToChecked();
+  }
+}
+
+}  // namespace bindings
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/platform/bindings/idl_member_installer.h b/third_party/blink/renderer/platform/bindings/idl_member_installer.h
new file mode 100644
index 0000000..9316b26
--- /dev/null
+++ b/third_party/blink/renderer/platform/bindings/idl_member_installer.h
@@ -0,0 +1,184 @@
+// 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_BINDINGS_IDL_MEMBER_INSTALLER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_IDL_MEMBER_INSTALLER_H_
+
+#include "base/containers/span.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "v8/include/v8-fast-api-calls.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class DOMWrapperWorld;
+
+namespace bindings {
+
+// IDLMemberInstaller is a set of utility functions to define IDL members as
+// ES properties.
+class PLATFORM_EXPORT IDLMemberInstaller final {
+  STATIC_ONLY(IDLMemberInstaller);
+
+ public:
+  // On which object the property is defined
+  enum class FlagLocation {
+    kInstance,
+    kPrototype,
+    kInterface,
+  };
+  // In which world the property is defined
+  enum class FlagWorld {
+    kMainWorld = 1 << 0,
+    kNonMainWorlds = 1 << 1,
+    kAllWorlds = kMainWorld | kNonMainWorlds,
+  };
+  // v8::Signature check against the receiver object
+  enum class FlagReceiverCheck {
+    kCheck,
+    kDoNotCheck,
+  };
+  // Cross origin access check
+  enum class FlagCrossOriginCheck {
+    kCheck,
+    kDoNotCheck,
+  };
+
+  // Web IDL attribute
+  struct AttributeConfig {
+    AttributeConfig& operator=(const AttributeConfig&) = delete;
+
+    const char* name;
+    v8::FunctionCallback callback_for_get;
+    v8::FunctionCallback callback_for_set;
+    unsigned v8_property_attribute : 3;       // v8::PropertyAttribute
+    unsigned location : 2;                    // FlagLocation
+    unsigned world : 2;                       // FlagWorld
+    unsigned receiver_check : 1;              // FlagReceiverCheck
+    unsigned cross_origin_check_for_get : 1;  // FlagCrossOriginCheck
+    unsigned cross_origin_check_for_set : 1;  // FlagCrossOriginCheck
+    unsigned v8_side_effect : 2;              // v8::SideEffectType
+    unsigned v8_cached_accessor : 2;  // V8PrivateProperty::CachedAccessor
+  };
+  static void InstallAttributes(v8::Isolate* isolate,
+                                const DOMWrapperWorld& world,
+                                v8::Local<v8::Template> instance_template,
+                                v8::Local<v8::Template> prototype_template,
+                                v8::Local<v8::Template> interface_template,
+                                v8::Local<v8::Signature> signature,
+                                base::span<const AttributeConfig> configs);
+  static void InstallAttributes(v8::Isolate* isolate,
+                                const DOMWrapperWorld& world,
+                                v8::Local<v8::Object> instance_object,
+                                v8::Local<v8::Object> prototype_object,
+                                v8::Local<v8::Object> interface_object,
+                                v8::Local<v8::Signature> signature,
+                                base::span<const AttributeConfig> configs);
+
+  // Web IDL constant
+  struct ConstantCallbackConfig {
+    ConstantCallbackConfig& operator=(const ConstantCallbackConfig&) = delete;
+
+    const char* name;
+    v8::AccessorNameGetterCallback callback;
+  };
+  static void InstallConstants(
+      v8::Isolate* isolate,
+      const DOMWrapperWorld& world,
+      v8::Local<v8::Template> instance_template,
+      v8::Local<v8::Template> prototype_template,
+      v8::Local<v8::Template> interface_template,
+      v8::Local<v8::Signature> signature,
+      base::span<const ConstantCallbackConfig> configs);
+
+  struct ConstantValueConfig {
+    ConstantValueConfig& operator=(const ConstantValueConfig&) = delete;
+
+    const char* name;
+    int64_t value;
+  };
+  static void InstallConstants(v8::Isolate* isolate,
+                               const DOMWrapperWorld& world,
+                               v8::Local<v8::Template> instance_template,
+                               v8::Local<v8::Template> prototype_template,
+                               v8::Local<v8::Template> interface_template,
+                               v8::Local<v8::Signature> signature,
+                               base::span<const ConstantValueConfig> configs);
+
+  // Web IDL operation
+  struct OperationConfig {
+    OperationConfig& operator=(const OperationConfig&) = delete;
+
+    const char* name;
+    v8::FunctionCallback callback;
+    unsigned length : 8;
+    unsigned v8_property_attribute : 3;  // v8::PropertyAttribute
+    unsigned location : 2;               // FlagLocation
+    unsigned world : 2;                  // FlagWorld
+    unsigned receiver_check : 1;         // FlagReceiverCheck
+    unsigned cross_origin_check : 1;     // FlagCrossOriginCheck
+    unsigned v8_side_effect : 2;         // v8::SideEffectType
+  };
+  static void InstallOperations(v8::Isolate* isolate,
+                                const DOMWrapperWorld& world,
+                                v8::Local<v8::Template> instance_template,
+                                v8::Local<v8::Template> prototype_template,
+                                v8::Local<v8::Template> interface_template,
+                                v8::Local<v8::Signature> signature,
+                                base::span<const OperationConfig> configs);
+  static void InstallOperations(v8::Isolate* isolate,
+                                const DOMWrapperWorld& world,
+                                v8::Local<v8::Object> instance_object,
+                                v8::Local<v8::Object> prototype_object,
+                                v8::Local<v8::Object> interface_object,
+                                v8::Local<v8::Signature> signature,
+                                base::span<const OperationConfig> configs);
+
+  struct NoAllocDirectCallOperationConfig {
+    OperationConfig operation_config;
+    v8::CFunction v8_c_function;
+  };
+  static void InstallOperations(
+      v8::Isolate* isolate,
+      const DOMWrapperWorld& world,
+      v8::Local<v8::Template> instance_template,
+      v8::Local<v8::Template> prototype_template,
+      v8::Local<v8::Template> interface_template,
+      v8::Local<v8::Signature> signature,
+      base::span<const NoAllocDirectCallOperationConfig> configs);
+
+  // Global property reference
+  // https://heycam.github.io/webidl/#define-the-global-property-references
+  // [LegacyNamespace]
+  // https://heycam.github.io/webidl/#LegacyNamespace
+  struct ExposedConstructConfig {
+    ExposedConstructConfig& operator=(const ExposedConstructConfig&) = delete;
+
+    const char* name;
+    v8::AccessorNameGetterCallback callback;
+  };
+  static void InstallExposedConstructs(
+      v8::Isolate* isolate,
+      const DOMWrapperWorld& world,
+      v8::Local<v8::Template> instance_template,
+      v8::Local<v8::Template> prototype_template,
+      v8::Local<v8::Template> interface_template,
+      v8::Local<v8::Signature> signature,
+      base::span<const ExposedConstructConfig> configs);
+  static void InstallExposedConstructs(
+      v8::Isolate* isolate,
+      const DOMWrapperWorld& world,
+      v8::Local<v8::Object> instance_object,
+      v8::Local<v8::Object> prototype_object,
+      v8::Local<v8::Object> interface_object,
+      v8::Local<v8::Signature> signature,
+      base::span<const ExposedConstructConfig> configs);
+};
+
+}  // namespace bindings
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_IDL_MEMBER_INSTALLER_H_
diff --git a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc
index f615ecbd..28fa129 100644
--- a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc
+++ b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc
@@ -607,8 +607,18 @@
     return false;
   }
 
-  avifROData raw_data = {image_data_->bytes(), image_data_->size()};
-  auto ret = avifDecoderParse(decoder_.get(), &raw_data);
+  // Chrome doesn't use XMP and Exif metadata. Ignoring XMP and Exif will ensure
+  // avifDecoderParse() isn't waiting for some tiny Exif payload hiding at the
+  // end of a file.
+  decoder_->ignoreXMP = AVIF_TRUE;
+  decoder_->ignoreExif = AVIF_TRUE;
+  auto ret = avifDecoderSetIOMemory(decoder_.get(), image_data_->bytes(),
+                                    image_data_->size());
+  if (ret != AVIF_RESULT_OK) {
+    DVLOG(1) << "avifDecoderSetIOMemory failed: " << avifResultToString(ret);
+    return false;
+  }
+  ret = avifDecoderParse(decoder_.get());
   if (ret != AVIF_RESULT_OK) {
     DVLOG(1) << "avifDecoderParse failed: " << avifResultToString(ret);
     return false;
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.cc
index ef4358fd..1c96e42 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/web_bundle_subresource_loader.cc
@@ -106,7 +106,10 @@
     }
     size_t offset = base::checked_cast<size_t>(uint64_offset);
     size_t len = std::min(data_.size() - offset, buffer.size());
-    memcpy(buffer.data(), &data_[offset], len);
+    if (len > 0) {
+      DCHECK_LT(offset, data_.size());
+      memcpy(buffer.data(), &data_[offset], len);
+    }
     result.bytes_read = len;
     return result;
   }
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index be3a9e2..d845a42 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -5879,6 +5879,13 @@
 crbug.com/106759 http/tests/devtools/command-line-api-inspect.js [ Pass Failure ]
 crbug.com/106759 http/tests/devtools/sources/debugger-console/debugger-command-line-api.js [ Pass Failure ]
 
+# Temporarily disabled to land DevTools change
+crbug.com/1136848 http/tests/devtools/sources/formatter-css.js [ Pass Failure ]
+crbug.com/1136848 http/tests/devtools/sources/formatter-js.js [ Pass Failure ]
+crbug.com/1136848 http/tests/devtools/sources/inline-styles-scripts-locations.js [ Pass Failure ]
+crbug.com/1136848 http/tests/devtools/sources/debugger-ui/script-formatter-breakpoints-2.js [ Pass Failure ]
+crbug.com/1136848 http/tests/devtools/sources/debugger-ui/script-formatter-breakpoints-3.js [ Pass Failure ]
+
 crbug.com/989665 [ Mac ] external/wpt/resource-timing/resource_timing_buffer_full_eventually.html [ Crash Pass ]
 crbug.com/989665 [ Linux ] virtual/omt-worker-fetch/external/wpt/resource-timing/resource_timing_buffer_full_eventually.html [ Crash Pass ]
 crbug.com/989665 [ Win ] virtual/omt-worker-fetch/external/wpt/resource-timing/resource_timing_buffer_full_eventually.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/accessibility/aria-owns-sends-notification.html b/third_party/blink/web_tests/accessibility/aria-owns-sends-notification.html
index eaf63d69..add3a2a 100644
--- a/third_party/blink/web_tests/accessibility/aria-owns-sends-notification.html
+++ b/third_party/blink/web_tests/accessibility/aria-owns-sends-notification.html
@@ -12,16 +12,12 @@
     var testRunner = function*() {
       assert_equals(axFutureParent.childrenCount, 0);
 
-      var expected_notifications = new Set();
-      expected_notifications.add("ChildrenChanged");
-      expected_notifications.add("MarkDirty");
-
-      while (expected_notifications.size) {
-        var notification = yield;
-        expected_notifications.delete(notification);
-      }
-
+      var notification = yield;
+      assert_equals(notification, "ChildrenChanged");
       assert_equals(axFutureParent.childrenCount, 1);
+
+      var notification = yield;
+      assert_equals(notification, "TextChanged");
     }();
     testRunner.next();
     var listener = function(notification) {
diff --git a/third_party/blink/web_tests/accessibility/text-change-notification.html b/third_party/blink/web_tests/accessibility/text-change-notification.html
index 73b4e9c8..947ffe5 100644
--- a/third_party/blink/web_tests/accessibility/text-change-notification.html
+++ b/third_party/blink/web_tests/accessibility/text-change-notification.html
@@ -37,31 +37,27 @@
         t.done();
     });
 
-    accessibleElementById('aria-label').setNotificationListener(function(notification) {
-        assert_equals(notification, 'MarkDirty');
+    accessibleElementById('aria-label').addNotificationListener(function(notification) {
+        assert_equals(notification, 'TextChanged');
         gotSuccessfulNotification();
-        accessibleElementById('aria-label').unsetNotificationListener();
     });
     document.getElementById('aria-label').setAttribute('aria-label', 'New aria-label');
 
-    accessibleElementById('title').setNotificationListener(function(notification) {
-        assert_equals(notification, 'MarkDirty');
+    accessibleElementById('title').addNotificationListener(function(notification) {
+        assert_equals(notification, 'TextChanged');
         gotSuccessfulNotification();
-        accessibleElementById('title').unsetNotificationListener();
     });
     document.getElementById('title').title = 'New title';
 
-    accessibleElementById('labelledby').setNotificationListener(function(notification) {
-        assert_equals(notification, 'MarkDirty');
+    accessibleElementById('labelledby').addNotificationListener(function(notification) {
+        assert_equals(notification, 'TextChanged');
         gotSuccessfulNotification();
-        accessibleElementById('labelledby').unsetNotificationListener();
     });
     document.getElementById('labelledby').setAttribute('aria-labelledby', 'label2');
 
-    accessibleElementById('labeled').setNotificationListener(function(notification) {
-        assert_equals(notification, 'MarkDirty');
+    accessibleElementById('labeled').addNotificationListener(function(notification) {
+        assert_equals(notification, 'TextChanged');
         gotSuccessfulNotification();
-        accessibleElementById('labeled').unsetNotificationListener();
     });
     document.getElementById('label1').setAttribute('for', 'labeled');
 }, "This test ensures that a change to an element's accessible text, even if indirect, sends a notification.");
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 21ae986..ac16a587 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
@@ -89560,7 +89560,7 @@
       ]
      ],
      "active-selection-021.html": [
-      "2061385d6c564c32ff2e36fc096df5b633d7ec2a",
+      "bfa7eee77706c3a64e5c3247c9aee1c46a457a7b",
       [
        null,
        [
@@ -92965,6 +92965,19 @@
      ]
     },
     "css-shadow-parts": {
+     "interaction-with-nested-pseudo-class.html": [
+      "1061e4b0e3501535d2bebf741e4986a2a6779c1a",
+      [
+       null,
+       [
+        [
+         "/css/css-shadow-parts/interaction-with-nested-pseudo-class-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "interaction-with-placeholder.html": [
       "a064789f06111bf5ce791650207bcee195d346ab",
       [
@@ -112351,6 +112364,19 @@
        {}
       ]
      ],
+     "text-decoration-color-selection-001.html": [
+      "beababcf4cd228fc40c2165ac3a410bc0aafd0d9",
+      [
+       null,
+       [
+        [
+         "/css/css-text-decor/reference/text-decoration-color-selection-001-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "text-decoration-color.html": [
       "1e1353d9fa67ea6ef0019fc499dfeaafae65fe87",
       [
@@ -194295,7 +194321,7 @@
        []
       ],
       "active-selection-021-ref.html": [
-       "7790a3fad8a36f1709fea6a4155ed5af0f3c49d7",
+       "a5d0e4e32a3545318320c734cb77bcd334078773",
        []
       ],
       "active-selection-025-ref.html": [
@@ -194789,6 +194815,10 @@
       "eee037eb8ffe8d29bf0902318211e05a7543fba3",
       []
      ],
+     "interaction-with-nested-pseudo-class-ref.html": [
+      "e3b99d43a69e6ff44899e6512237978883df06cf",
+      []
+     ],
      "interaction-with-placeholder-ref.html": [
       "11943c229a0ea76893039b1306bb38402c71f6ad",
       []
@@ -199648,6 +199678,10 @@
        "3ae7777ef06cf3fa3bebcf385d8462cf8453ae64",
        []
       ],
+      "text-decoration-color-selection-001-ref.html": [
+       "d9811874eef87fe37bf5173c0dccc380907cf439",
+       []
+      ],
       "text-decoration-line-010-ref.xht": [
        "6bcba28f191d03b2106131f27c7a2f88667cc9ca",
        []
@@ -237110,7 +237144,7 @@
       []
      ],
      "mock-imagecapture.js": [
-      "035b5241ae989161bfc604b5607a81734a9bdb8d",
+      "a8f5c896b1f2cc2c90240bd053d218c28dc549dd",
       []
      ],
      "mock-screenenumeration.js": [
@@ -237170,7 +237204,7 @@
       []
      ],
      "webxr-test.js": [
-      "6b6c41de0c4c1082affb2ec54208c326a755b425",
+      "c661971285cd01b31ab57ede8e543293dfc56948",
       []
      ],
      "webxr-test.js.headers": [
@@ -306394,8 +306428,15 @@
        {}
       ]
      ],
+     "is-where-not.html": [
+      "f3d27db317cee1316efaba3f89d8812f726f09c7",
+      [
+       null,
+       {}
+      ]
+     ],
      "is-where-parsing.html": [
-      "33cb6ad726b8eef630d03ffbba243c066e004d3e",
+      "b93cbda6749b12d95bae28e05f27b0098ab6b7a1",
       [
        null,
        {}
@@ -359568,6 +359609,15 @@
          {}
         ]
        ],
+       "radio-double-activate-pseudo.html": [
+        "287dc7d58edddacb3bd282eae8450f89f5128345",
+        [
+         null,
+         {
+          "testdriver": true
+         }
+        ]
+       ],
        "radio-groupname-case.html": [
         "3c54aca3e76bafe4c409ed33b7833dc982fea693",
         [
@@ -417026,7 +417076,7 @@
        ]
       ],
       "offlineaudiocontext-detached-execution-context.tentative.html": [
-       "ba44829f122d9ad0064b4b793578326c8190ce50",
+       "66d62cf6aa4e210b6fa2228b2ddfcd9724241d5b",
        [
         null,
         {}
@@ -441780,6 +441830,13 @@
      }
     },
     "css-text-decor": {
+     "text-decoration-color-selection-002.html": [
+      "1ee903c08a45decef3206668b24726e064aa3369",
+      [
+       null,
+       {}
+      ]
+     ],
      "text-decoration-visibility-001.xht": [
       "1451ae9c6b5199bacb758f31b906a6753c1f99e4",
       [
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-input-element/radio-double-activate-pseudo.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-input-element/radio-double-activate-pseudo.html
new file mode 100644
index 0000000..287dc7d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-input-element/radio-double-activate-pseudo.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="author" title="Joey Arhar" href="mailto:jarhar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<!-- This behavior is not explicitly specified. -->
+
+<input type=radio id=radioinput>
+
+<script>
+  promise_test(async () => {
+    await test_driver.send_keys(radioinput, ' ');
+    await test_driver.send_keys(radioinput, ' ');
+    assert_equals(document.querySelector(':active'), null,
+      `If the radio doesn't have the :active pseudo selector, nothing else should either.`);
+  }, `<input type=radio> shouldn't have the :active pseudo element after pressing the spacebar twice.`);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/mock-imagecapture.js b/third_party/blink/web_tests/external/wpt/resources/chromium/mock-imagecapture.js
index 035b524..a8f5c89 100644
--- a/third_party/blink/web_tests/external/wpt/resources/chromium/mock-imagecapture.js
+++ b/third_party/blink/web_tests/external/wpt/resources/chromium/mock-imagecapture.js
@@ -234,14 +234,13 @@
     }
 
     async isPanTiltZoomPermissionGranted() {
-      if (this.panTiltZoomPermissionStatus_) {
-        return (this.panTiltZoomPermissionStatus_.state == "granted");
+      if (!this.panTiltZoomPermissionStatus_) {
+        this.panTiltZoomPermissionStatus_ = await navigator.permissions.query({
+          name: "camera",
+          panTiltZoom: true
+        });
       }
-      this.panTiltZoomPermissionStatus_ = await navigator.permissions.query({
-        name: "camera",
-        panTiltZoom: true
-      });
-      return (this.panTiltZoomPermissionStatus_.state == "granted");
+      return this.panTiltZoomPermissionStatus_.state == "granted";
     }
 
     state() {
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/webxr-test.js b/third_party/blink/web_tests/external/wpt/resources/chromium/webxr-test.js
index a31bdc9..c661971 100644
--- a/third_party/blink/web_tests/external/wpt/resources/chromium/webxr-test.js
+++ b/third_party/blink/web_tests/external/wpt/resources/chromium/webxr-test.js
@@ -341,17 +341,6 @@
     "immersive-ar": device.mojom.XRSessionMode.kImmersiveAr,
   };
 
-  static environmentBlendModeToMojoMap = {
-    "opaque": device.mojom.XREnvironmentBlendMode.kOpaque,
-    "alpha-blend": device.mojom.XREnvironmentBlendMode.kAlphaBlend,
-    "additive": device.mojom.XREnvironmentBlendMode.kAdditive,
-  };
-
-  static interactionModeToMojoMap = {
-    "screen-space": device.mojom.XRInteractionMode.kScreenSpace,
-    "world-space": device.mojom.XRInteractionMode.kWorldSpace,
-  };
-
   constructor(fakeDeviceInit, service) {
     this.sessionClient_ = new device.mojom.XRSessionClientPtr();
     this.presentation_provider_ = new MockXRPresentationProvider();
@@ -430,8 +419,6 @@
     }
 
     this.defaultFramebufferScale_ = default_framebuffer_scale;
-    this.enviromentBlendMode_ = this._convertBlendModeToEnum(fakeDeviceInit.environmentBlendMode);
-    this.interactionMode_ = this._convertInteractionModeToEnum(fakeDeviceInit.interactionMode);
 
     // This appropriately handles if the coordinates are null
     this.setBoundsGeometry(fakeDeviceInit.boundsCoordinates);
@@ -454,26 +441,6 @@
     return sessionModes.map(mode => this._convertModeToEnum(mode));
   }
 
-  _convertBlendModeToEnum(blendMode) {
-    if (blendMode in MockRuntime.environmentBlendModeToMojoMap) {
-      return MockRuntime.environmentBlendModeToMojoMap[blendMode];
-    } else {
-      if (this.supportedModes_.includes(device.mojom.XRSessionMode.kImmersiveAr)) {
-        return device.mojom.XREnvironmentBlendMode.kAdditive;
-      } else if (this.supportedModes_.includes(device.mojom.XRSessionMode.kImmersiveVr)) {
-        return device.mojom.XREnvironmentBlendMode.kOpaque;
-      }
-    }
-  }
-
-  _convertInteractionModeToEnum(interactionMode) {
-    if (interactionMode in MockRuntime.interactionModeToMojoMap) {
-      return MockRuntime.interactionModeToMojoMap[interactionMode];
-    } else {
-      return device.mojom.XRInteractionMode.kWorldSpace;
-    }
-  }
-
   // Test API methods.
   disconnect() {
     this.service_.removeRuntime(this);
@@ -1052,9 +1019,7 @@
             deviceConfig: {
               defaultFramebufferScale: this.defaultFramebufferScale_,
               supportsViewportScaling: true
-            },
-            enviromentBlendMode: this.enviromentBlendMode_,
-            interactionMode: this.interactionMode_
+            }
           }
         });
       } else {
diff --git a/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_environmentBlendMode.https.html b/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_environmentBlendMode.https.html
index 28f31da..da2ddc28 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_environmentBlendMode.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_environmentBlendMode.https.html
@@ -21,4 +21,4 @@
         assert_in_array(session.environmentBlendMode, ["opaque", "additive"]);
       }, TRACKED_IMMERSIVE_DEVICE, 'immersive-vr', {});
 </script>
-</body>
\ No newline at end of file
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_interactionMode.https.html b/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_interactionMode.https.html
deleted file mode 100644
index 89cdc80..0000000
--- a/third_party/blink/web_tests/external/wpt/webxr/ar-module/xrSession_interactionMode.https.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<!DOCTYPE html>
-<body>
-  <script src=/resources/testharness.js></script>
-  <script src=/resources/testharnessreport.js></script>
-  <script src="../resources/webxr_util.js"></script>
-  <script src="../resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
-  <script>
-    const VR_HMD_DEVICE = {
-      supportsImmersive: true,
-      supportedModes: [ "immersive-vr"],
-      views: VALID_VIEWS,
-      viewerOrigin: IDENTITY_TRANSFORM,
-      supportedFeatures: ALL_FEATURES,
-      environmentBlendMode: "opaque",
-      interactionMode: "world-space"
-    };
-    xr_session_promise_test(
-      "Tests interactionMode for an VR_HMD_DEVICE",
-      (session) => {
-        assert_equals(session.interactionMode, "world-space");
-      }, VR_HMD_DEVICE, 'immersive-vr', {});
-
-    const VR_SCREEN_DEVICE = {
-      supportsImmersive: true,
-      supportedModes: [ "immersive-vr"],
-      views: VALID_VIEWS,
-      viewerOrigin: IDENTITY_TRANSFORM,
-      supportedFeatures: ALL_FEATURES,
-      environmentBlendMode: "opaque",
-      interactionMode: "screen-space"
-    };
-    xr_session_promise_test(
-      "Tests interactionMode for an VR_SCREEN_DEVICE",
-      (session) => {
-        assert_equals(session.interactionMode, "screen-space");
-      }, VR_SCREEN_DEVICE, 'immersive-vr', {});
-
-    const AR_HMD_DEVICE = {
-      supportsImmersive: true,
-      supportedModes: [ "immersive-ar"],
-      views: VALID_VIEWS,
-      viewerOrigin: IDENTITY_TRANSFORM,
-      supportedFeatures: ALL_FEATURES,
-      environmentBlendMode: "additive",
-      interactionMode: "world-space"
-    };
-    xr_session_promise_test(
-      "Tests interactionMode for an AR_HMD_DEVICE",
-      (session) => {
-        assert_equals(session.interactionMode, "world-space");
-      }, AR_HMD_DEVICE, 'immersive-ar', {});
-
-    const AR_SCREEN_DEVICE = {
-      supportsImmersive: true,
-      supportedModes: [ "immersive-ar"],
-      views: VALID_VIEWS,
-      viewerOrigin: IDENTITY_TRANSFORM,
-      supportedFeatures: ALL_FEATURES,
-      environmentBlendMode: "opaque",
-      interactionMode: "screen-space"
-    };
-    xr_session_promise_test(
-      "Tests interactionMode for an AR_SCREEN_DEVICE",
-      (session) => {
-        assert_equals(session.interactionMode, "screen-space");
-      }, AR_SCREEN_DEVICE, 'immersive-ar', {});
-
-    const INLINE_SCREEN_DEVICE = {
-      supportsImmersive: true,
-      supportedModes: [ "inline"],
-      views: VALID_VIEWS,
-      viewerOrigin: IDENTITY_TRANSFORM,
-      supportedFeatures: ALL_FEATURES,
-      environmentBlendMode: "opaque",
-      interactionMode: "screen-space"
-    };
-    xr_session_promise_test(
-      "Tests interactionMode for a INLINE_SCREEN_DEVICE",
-      (session) => {
-        assert_equals(session.interactionMode, "screen-space");
-      }, INLINE_SCREEN_DEVICE, 'inline', {});
-</script>
-</body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/ar_dom_overlay.https.html b/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/ar_dom_overlay.https.html
index 250adf9..78a8ba20 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/ar_dom_overlay.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/dom-overlay/ar_dom_overlay.https.html
@@ -39,8 +39,6 @@
   views: VALID_VIEWS,
   viewerOrigin: IDENTITY_TRANSFORM,
   supportedFeatures: ALL_FEATURES,
-  environmentBlendMode: "alpha-blend",
-  interactionMode: "screen-space"
 };
 
 let testBasicProperties = function(overlayElement, session, fakeDeviceController, t) {
diff --git a/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_test_constants.js b/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_test_constants.js
index 40643d0..139ab77 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_test_constants.js
+++ b/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_test_constants.js
@@ -132,9 +132,7 @@
     supportedModes: [ "inline", "immersive-vr"],
     views: VALID_VIEWS,
     viewerOrigin: IDENTITY_TRANSFORM,
-    supportedFeatures: ALL_FEATURES,
-    environmentBlendMode: "opaque",
-    interactionMode: "world-space"
+    supportedFeatures: ALL_FEATURES
 };
 
 const IMMERSIVE_AR_DEVICE = {
@@ -142,9 +140,7 @@
   supportedModes: [ "inline", "immersive-ar"],
   views: VALID_VIEWS,
   viewerOrigin: IDENTITY_TRANSFORM,
-  supportedFeatures: ALL_FEATURES,
-  environmentBlendMode: "additive",
-  interactionMode: "screen-space"
+  supportedFeatures: ALL_FEATURES
 };
 
 const VALID_NON_IMMERSIVE_DEVICE = {
@@ -152,9 +148,7 @@
     supportedModes: ["inline"],
     views: NON_IMMERSIVE_VIEWS,
     viewerOrigin: IDENTITY_TRANSFORM,
-    supportedFeatures: ALL_FEATURES,
-    environmentBlendMode: "opaque",
-    interactionMode: "screen-space"
+    supportedFeatures: ALL_FEATURES
 };
 
 const VALID_CONTROLLER = {
diff --git a/third_party/blink/web_tests/http/tests/loading/wbn/resources/empty-resource/empty.js b/third_party/blink/web_tests/http/tests/loading/wbn/resources/empty-resource/empty.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/loading/wbn/resources/empty-resource/empty.js
diff --git a/third_party/blink/web_tests/http/tests/loading/wbn/resources/generate-test-wbns.sh b/third_party/blink/web_tests/http/tests/loading/wbn/resources/generate-test-wbns.sh
index 712fedb..403b1c16 100755
--- a/third_party/blink/web_tests/http/tests/loading/wbn/resources/generate-test-wbns.sh
+++ b/third_party/blink/web_tests/http/tests/loading/wbn/resources/generate-test-wbns.sh
@@ -32,3 +32,10 @@
   -primaryURL https://localhost:8443/loading/wbn/resources/wbn/server/wbn-subresource-third-party-origin-trial/script.js \
   -dir wbn-subresource-third-party-origin-trial/ \
   -o wbn/wbn-subresource-third-party-origin-trial.wbn
+
+gen-bundle \
+  -version b1 \
+  -baseURL http://127.0.0.1:8000/loading/wbn/resources/wbn/ \
+  -primaryURL http://127.0.0.1:8000/loading/wbn/resources/wbn/empty.js \
+  -dir empty-resource/ \
+  -o wbn/empty-resource.wbn
diff --git a/third_party/blink/web_tests/http/tests/loading/wbn/resources/wbn/empty-resource.wbn b/third_party/blink/web_tests/http/tests/loading/wbn/resources/wbn/empty-resource.wbn
new file mode 100644
index 0000000..c6d0807
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/loading/wbn/resources/wbn/empty-resource.wbn
Binary files differ
diff --git a/third_party/blink/web_tests/http/tests/loading/wbn/subresource-loading/subresource-loading-empty-resource-crash.html b/third_party/blink/web_tests/http/tests/loading/wbn/subresource-loading/subresource-loading-empty-resource-crash.html
new file mode 100644
index 0000000..df9cf22
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/loading/wbn/subresource-loading/subresource-loading-empty-resource-crash.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+  <link
+    rel="webbundle"
+    href="../resources/wbn/empty-resource.wbn"
+    resources="http://127.0.0.1:8000/loading/wbn/resources/wbn/empty.js"
+  />
+  <script>
+    promise_test(async () => {
+      const response = await fetch(
+        "http://127.0.0.1:8000/loading/wbn/resources/wbn/empty.js"
+      );
+      assert_true(response.ok);
+    }, "Loading an empty resource in a bundle should not cause a crash");
+  </script>
+</body>
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/resources/origintrials-worker.js b/third_party/blink/web_tests/http/tests/origin_trials/resources/origintrials-worker.js
index 83e8e605..a72bea09 100644
--- a/third_party/blink/web_tests/http/tests/origin_trials/resources/origintrials-worker.js
+++ b/third_party/blink/web_tests/http/tests/origin_trials/resources/origintrials-worker.js
@@ -37,11 +37,6 @@
     assert_false('normalAttribute' in testObject);
     assert_equals(testObject.normalAttribute, undefined);
   }, 'Attribute should not exist in ' + worker_type + ' worker');
-  test(() => {
-    var testObject = self.internals.originTrialsTest();
-    assert_false('CONSTANT' in testObject);
-    assert_equals(testObject.CONSTANT, undefined);
-  }, 'Constant should not exist in ' + worker_type + ' worker');
   done();
 }
 
@@ -119,17 +114,6 @@
       assert_idl_attribute(testObject, 'normalAttribute');
       assert_true(testObject.normalAttribute, 'Attribute should return boolean value');
     }, 'Attribute should exist and return value in ' + worker_type + ' worker');
-  test(() => {
-      var testObject = self.internals.originTrialsTest();
-      assert_idl_attribute(testObject, 'CONSTANT');
-      assert_equals(testObject.CONSTANT, 1, 'Constant should return integer value');
-    }, 'Constant should exist and return value in ' + worker_type + ' worker');
-  test(() => {
-      var testObject = self.internals.originTrialsTest();
-      assert_idl_attribute(testObject, 'CONSTANT');
-      testObject.CONSTANT = 10;
-      assert_equals(testObject.CONSTANT, 1, 'Constant should not be modifiable');
-    }, 'Constant should exist and not be modifiable in ' + worker_type + ' worker');
   done();
 }
 
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/resources/origintrials.js b/third_party/blink/web_tests/http/tests/origin_trials/resources/origintrials.js
index b2767d9..84d986b 100644
--- a/third_party/blink/web_tests/http/tests/origin_trials/resources/origintrials.js
+++ b/third_party/blink/web_tests/http/tests/origin_trials/resources/origintrials.js
@@ -83,19 +83,6 @@
   assert_true(media_list.mediaText.indexOf("not all") === -1);
 }
 
-// Verify that the given constant exists, and returns the expected value, and
-// is not modifiable.
-expect_constant = (constant_name, constant_value, get_value_func) => {
-  var testObject = internals.originTrialsTest();
-  var testInterface = testObject.constructor;
-  assert_own_property(testInterface, constant_name);
-  assert_equals(get_value_func(testInterface), constant_value,
-    'Constant should return expected value');
-  testInterface[constant_name] = constant_value + 1;
-  assert_equals(get_value_func(testInterface), constant_value,
-    'Constant should not be modifiable');
-}
-
 // Verify that given member does not exist, and does not provide a value
 // (i.e. is undefined).
 expect_member_fails = (member_name) => {
@@ -186,10 +173,6 @@
       expect_member_fails('normalAttribute');
     }, 'Attribute should not exist, with trial disabled');
 
-  test(() => {
-      expect_static_member_fails('CONSTANT');
-    }, 'Constant should not exist, with trial disabled');
-
   if (!skip_worker) {
     fetch_tests_from_worker(new Worker('resources/disabled-worker.js'));
   }
@@ -278,12 +261,6 @@
         });
     }, 'Attribute should exist on object and return value');
 
-  test(() => {
-      expect_constant('CONSTANT', 1, (testObject) => {
-          return testObject.CONSTANT;
-        });
-    }, 'Constant should exist on interface and return value');
-
   fetch_tests_from_worker(new Worker('resources/enabled-worker.js'));
 };
 
@@ -385,12 +362,6 @@
     }, 'Static method should exist and return value, regardless of trial' + description_suffix);
 
   test(() => {
-      expect_constant('UNCONDITIONAL_CONSTANT', 99, (testObject) => {
-          return testObject.UNCONDITIONAL_CONSTANT;
-        });
-    }, 'Constant should exist on interface and return value, regardless of trial' + description_suffix);
-
-  test(() => {
       expect_dictionary_member('unconditionalBool');
     }, 'Dictionary output from method should return member value, regardless of trial' + description_suffix);
 
@@ -539,12 +510,6 @@
         });
     }, 'Static method should exist on partial interface and return value');
 
-  test(() => {
-      expect_constant('CONSTANT_PARTIAL', 2, (testObject) => {
-          return testObject.CONSTANT_PARTIAL;
-        });
-    }, 'Constant should exist on partial interface and return value');
-
   // Tests for combination of [RuntimeEnabled] and [SecureContext]
   test(() => {
       expect_member('secureAttribute', (testObject) => {
@@ -645,9 +610,6 @@
   test(() => {
       expect_static_member_fails('staticMethodPartial');
     }, 'Static method should not exist on partial interface, with trial disabled');
-  test(() => {
-      expect_static_member_fails('CONSTANT_PARTIAL');
-    }, 'Constant should not exist on partial interface, with trial disabled');
 
   // Tests for combination of [RuntimeEnabled] and [SecureContext]
   test(() => {
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 8811578a..8a17898b 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
@@ -8816,7 +8816,6 @@
     setter overlaysContent
 interface VirtualKeyboardGeometryChangeEvent : Event
     attribute @@toStringTag
-    getter boundingRect
     method constructor
 interface VisibilityStateEntry : PerformanceEntry
     attribute @@toStringTag
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/ar/iframe-oopif.sub.https.html b/third_party/blink/web_tests/wpt_internal/webxr/ar/iframe-oopif.sub.https.html
index 1f077212..28ef51f 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/ar/iframe-oopif.sub.https.html
+++ b/third_party/blink/web_tests/wpt_internal/webxr/ar/iframe-oopif.sub.https.html
@@ -14,8 +14,6 @@
   views: VALID_VIEWS,
   viewerOrigin: IDENTITY_TRANSFORM,
   supportedFeatures: ALL_FEATURES,
-  environmentBlendMode: "alpha-blend",
-  interactionMode: "screen-space"
 };
 
 // Arbitrary message for notifying the parent frame
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js
index 95222995..1beeef3c 100644
--- a/third_party/closure_compiler/externs/automation.js
+++ b/third_party/closure_compiler/externs/automation.js
@@ -39,7 +39,6 @@
   DOCUMENT_SELECTION_CHANGED: 'documentSelectionChanged',
   DOCUMENT_TITLE_CHANGED: 'documentTitleChanged',
   DROPEFFECT_CHANGED: 'dropeffectChanged',
-  EDITABLE_TEXT_CHANGED: 'editableTextChanged',
   ENABLED_CHANGED: 'enabledChanged',
   END_OF_TEST: 'endOfTest',
   EXPANDED: 'expanded',
diff --git a/third_party/closure_compiler/externs/chrome.js b/third_party/closure_compiler/externs/chrome.js
index d30f339c..0619bdce 100644
--- a/third_party/closure_compiler/externs/chrome.js
+++ b/third_party/closure_compiler/externs/chrome.js
@@ -486,6 +486,10 @@
 Tab.prototype.url;
 
 
+/** @type {string|undefined} */
+Tab.prototype.pendingUrl;
+
+
 // TODO: Make this field optional once dependent projects have been updated.
 /** @type {string} */
 Tab.prototype.title;
diff --git a/third_party/closure_compiler/externs/chrome_extensions.js b/third_party/closure_compiler/externs/chrome_extensions.js
index f2bd832..747ab45 100644
--- a/third_party/closure_compiler/externs/chrome_extensions.js
+++ b/third_party/closure_compiler/externs/chrome_extensions.js
@@ -269,6 +269,34 @@
 
 
 /** @type {!ChromeSetting} */
+chrome.accessibilityFeatures.caretHighlight;
+
+
+/** @type {!ChromeSetting} */
+chrome.accessibilityFeatures.cursorHighlight;
+
+
+/** @type {!ChromeSetting} */
+chrome.accessibilityFeatures.cursorColor;
+
+
+/** @type {!ChromeSetting} */
+chrome.accessibilityFeatures.dockedMagnifier;
+
+
+/** @type {!ChromeSetting} */
+chrome.accessibilityFeatures.focusHighlight;
+
+
+/** @type {!ChromeSetting} */
+chrome.accessibilityFeatures.selectToSpeak;
+
+
+/** @type {!ChromeSetting} */
+chrome.accessibilityFeatures.switchAccess;
+
+
+/** @type {!ChromeSetting} */
 chrome.accessibilityFeatures.animationPolicy;
 
 
@@ -2349,7 +2377,7 @@
  * Returns byte string associated with the data item stored in a platform
  * specific storage.
  * @param {!string} item Item name (can have containers separated by '/').
- * @param {(function(!ArrayBuffer): void)=} callback Called back with the
+ * @param {(function((!ArrayBuffer|undefined)): void)=} callback Called back with the
  *     response.
  */
 chrome.enterprise.reportingPrivate.getDeviceData = function(item, callback) {};
@@ -2358,7 +2386,7 @@
  * Stores byte string associated with the data item in a platform
  * specific storage.
  * @param {!string} item Item name (can have containers separated by '/').
- * @param {!ArrayBuffer} data Byte string to associate with the data item.
+ * @param {!ArrayBuffer|undefined} data Byte string to associate with the data item.
  * @param {(function(): void)=} callback Called back with the response.
  */
 chrome.enterprise.reportingPrivate.setDeviceData = function(
@@ -2384,6 +2412,7 @@
  *   serialNumber: string,
  *   screenLockSecured: chrome.enterprise.reportingPrivate.SettingValue,
  *   diskEncrypted: chrome.enterprise.reportingPrivate.SettingValue,
+ *   macAddresses: (!Array<string>|undefined),
  * }}
  */
 chrome.enterprise.reportingPrivate.DeviceInfo;
@@ -2628,6 +2657,10 @@
 chrome.runtime.Manifest.prototype.description;
 
 
+/** @type {!Object<string, string>} */
+chrome.runtime.Manifest.prototype.icons;
+
+
 /** @type {!chrome.runtime.Manifest.Oauth2|undefined} */
 chrome.runtime.Manifest.prototype.oauth2;
 
@@ -2650,6 +2683,9 @@
  */
 chrome.runtime.Manifest.prototype.kiosk_enabled;
 
+/** @type {string|undefined} */
+chrome.runtime.Manifest.prototype.replacement_web_app;
+
 
 
 /**
@@ -2756,8 +2792,63 @@
 
 
 /**
- *
- * @param {function(!Object)} callback
+ * The operating system chrome is running on.
+ * @see https://developer.chrome.com/apps/runtime#type-PlatformOs
+ * @enum {string}
+ */
+chrome.runtime.PlatformOs = {
+  ANDROID: '',
+  CROS: '',
+  LINUX: '',
+  MAC: '',
+  OPENBSD: '',
+  WIN: '',
+};
+
+
+/**
+ * The machine's processor architecture.
+ * @see https://developer.chrome.com/apps/runtime#type-PlatformArch
+ * @enum {string}
+ */
+chrome.runtime.PlatformArch = {
+  ARM: '',
+  ARM64: '',
+  MIPS: '',
+  MIPS64: '',
+  X86_32: '',
+  X86_64: '',
+};
+
+
+/**
+ * The native client architecture.
+ * @see https://developer.chrome.com/apps/runtime#type-PlatformNaclArch
+ * @enum {string}
+ */
+chrome.runtime.PlatformNaclArch = {
+  ARM: '',
+  MIPS: '',
+  MIPS64: '',
+  X86_32: '',
+  X86_64: '',
+};
+
+
+/**
+ * @see https://developer.chrome.com/apps/runtime#type-PlatformInfo
+ * @typedef {{
+ *   os: !chrome.runtime.PlatformOs,
+ *   arch: !chrome.runtime.PlatformArch,
+ *   nacl_arch: !chrome.runtime.PlatformNaclArch,
+ * }}
+ */
+chrome.runtime.PlatformInfo;
+
+
+/**
+ * @see https://developer.chrome.com/extensions/runtime#type-PlatformInfo
+ * @param {function(!chrome.runtime.PlatformInfo)} callback
  * @return {undefined}
  */
 chrome.runtime.getPlatformInfo = function(callback) {};
@@ -2778,6 +2869,10 @@
 chrome.runtime.onConnectExternal;
 
 
+/** @type {!chrome.runtime.PortEvent} */
+chrome.runtime.onConnectNative;
+
+
 /** @type {!ChromeObjectEvent} */
 chrome.runtime.onInstalled;
 
@@ -2847,6 +2942,13 @@
 
 
 /**
+ * @const {number}
+ * @see https://developer.chrome.com/extensions/tabs#property-TAB_ID_NONE
+ */
+chrome.tabs.TAB_ID_NONE = -1;
+
+
+/**
  * @typedef {?{
  *   code: (string|undefined),
  *   file: (string|undefined),
@@ -3032,8 +3134,8 @@
 /**
  * @see https://developer.chrome.com/extensions/tabs#method-highlight
  * @param {!chrome.tabs.HighlightInfo} highlightInfo
- * @param {function(!ChromeWindow): void} callback Callback function invoked
- *    with each appropriate Window.
+ * @param {function(!ChromeWindow): void=} callback Callback function invoked
+ *    for each window whose tabs were highlighted.
  * @return {undefined}
  */
 chrome.tabs.highlight = function(highlightInfo, callback) {};
@@ -4252,6 +4354,20 @@
 chrome.management.generateAppForLink = function(url, title, opt_callback) {};
 
 
+/**
+ * @param {function():void=} callback
+ * @return {undefined}
+ */
+chrome.management.installReplacementWebApp = function(callback) {};
+
+/**
+ * Event whose listeners take an ExtensionInfo parameter.
+ * @interface
+ * @extends {ChromeBaseEvent<function(!ExtensionInfo)>}
+ */
+function ChromeExtensionInfoEvent() {};
+
+
 /** @type {!ChromeExtensionInfoEvent} */
 chrome.management.onInstalled;
 
@@ -4973,6 +5089,57 @@
 
 
 /**
+ * @enum {string}
+ * @see https://developer.chrome.com/extensions/input.ime#type-AssistiveWindowType
+ */
+chrome.input.ime.AssistiveWindowType = {
+  UNDO: '',
+};
+
+
+/**
+ * Properties of the assistive window.
+ * @typedef {{
+ *   type: !chrome.input.ime.AssistiveWindowType,
+ *   visible: boolean
+ * }}
+ * @see https://developer.chrome.com/extensions/input.ime#type-AssistiveWindowProperties
+ */
+chrome.input.ime.AssistiveWindowProperties;
+
+
+/**
+ * Shows/Hides an assistive window with the given properties.
+ * @param {{
+ *   contextID: number,
+ *   properties: !chrome.input.ime.AssistiveWindowProperties
+ * }} parameters
+ * @param {function(boolean): void=} callback Called when the operation
+ *     completes.
+ * @see https://developer.chrome.com/extensions/input.ime#method-setAssistiveWindowProperties
+ */
+chrome.input.ime.setAssistiveWindowProperties = function(
+    parameters, callback) {};
+
+/**
+ * @enum {string}
+ * @see https://developer.chrome.com/extensions/input.ime#type-AssistiveWindowButton
+ */
+chrome.input.ime.AssistiveWindowButton = {
+  UNDO: '',
+  ADD_TO_DICTIONARY: '',
+};
+
+
+/**
+ * This event is sent when a button in an assistive window is clicked.
+ * @type {!ChromeEvent}
+ * @see https://developer.chrome.com/extensions/input.ime#event-onAssistiveWindowButtonClicked
+ */
+chrome.input.ime.onAssistiveWindowButtonClicked;
+
+
+/**
  * @param {!Object<string,(string|Array<Object<string,(string|boolean)>>)>}
  *     parameters An object with 'engineID' (string) and 'items'
  *     (array of object) keys.
@@ -6969,6 +7136,60 @@
  */
 chrome.system.display.onDisplayChanged;
 
+/**
+ * @const
+ * @see https://developer.chrome.com/extensions/system_memory
+ */
+chrome.system.memory = {};
+
+/**
+ * Get physical memory information.
+ * @param {function(!chrome.system.memory.MemoryInfo)} callback
+ * @return {undefined}
+ */
+chrome.system.memory.getInfo = function(callback) {};
+
+/**
+ * @constructor
+ */
+chrome.system.memory.MemoryInfo = function() {};
+
+
+/** @type {number} */
+chrome.system.memory.MemoryInfo.prototype.capacity;
+
+
+/** @type {number} */
+chrome.system.memory.MemoryInfo.prototype.availableCapacity;
+
+/**
+ * @const
+ * @see http://developer.chrome.com/apps/system_network.html
+ */
+chrome.system.network = {};
+
+/**
+ * @param {function(!Array<!chrome.system.network.NetworkInterface>)} callback
+ * @return {undefined}
+ */
+chrome.system.network.getNetworkInterfaces = function(callback) {};
+
+/**
+ * @interface
+ */
+chrome.system.network.NetworkInterface = function() {};
+
+/**
+ * @const {string} The underlying name of the adapter. On *nix, this will
+ *     typically be "eth0", "wlan0", etc.
+ */
+chrome.system.network.NetworkInterface.prototype.name;
+
+/** @const {string} The available IPv4/6 address. */
+chrome.system.network.NetworkInterface.prototype.address;
+
+/** @const {number} The prefix length */
+chrome.system.network.NetworkInterface.prototype.prefixLength;
 
 /**
  * @const
@@ -7445,15 +7666,6 @@
 ChromeWindow.prototype.alwaysOnTop;
 
 
-
-/**
- * Event whose listeners take an ExtensionInfo parameter.
- * @interface
- * @extends {ChromeBaseEvent<function(!ExtensionInfo)>}
- */
-function ChromeExtensionInfoEvent() {}
-
-
 /**
  * @see http://developer.chrome.com/extensions/pushMessaging.html
  * @const
@@ -7983,7 +8195,7 @@
  * Listener will receive an object that maps each key to its StorageChange,
  * and the namespace ("sync" or "local") of the storage area the changes
  * are for.
- * @see https://developer.chrome.com/extensions/storage.html
+ * @see https://developer.chrome.com/extensions/storage#event-onChanged
  * @interface
  * @extends {ChromeBaseEvent<function(!Object<string, !StorageChange>, string)>}
  */
@@ -7991,6 +8203,18 @@
 
 
 /**
+ * The event listener for StorageArea receives an Object mapping each
+ * key that changed to its corresponding StorageChange for that item.
+ *
+ * Listener will receive an object that maps each key to its StorageChange.
+ * @see https://developer.chrome.com/extensions/storage#type-StorageArea
+ * @interface
+ * @extends {ChromeBaseEvent<function(!Object<string, !StorageChange>)>}
+ */
+function StorageAreaChangeEvent() {}
+
+
+/**
  * @see https://developer.chrome.com/extensions/storage.html#type-StorageChange
  * @constructor
  */
@@ -8065,6 +8289,12 @@
 StorageArea.prototype.clear = function(opt_callback) {};
 
 
+/**
+ * Fired when one or more items change.
+ * @type {!StorageAreaChangeEvent}
+ */
+StorageArea.prototype.onChanged;
+
 
 /**
  * @see https://developer.chrome.com/extensions/types.html#type-ChromeSetting
@@ -10594,6 +10824,20 @@
  */
 chrome.inputMethodPrivate = {};
 
+/**
+ * @enum {string}
+ */
+chrome.inputMethodPrivate.InputModeType = {
+  NO_KEYBOARD: '',
+  TEXT: '',
+  TEL: '',
+  URL: '',
+  EMAIL: '',
+  NUMERIC: '',
+  DECIMAL: '',
+  SEARCH: '',
+};
+
 
 /**
  * @enum {string}
@@ -10638,6 +10882,8 @@
 /** @type {number} */
 chrome.inputMethodPrivate.InputContext.prototype.contextID;
 
+/** @type {chrome.inputMethodPrivate.InputModeType} */
+chrome.inputMethodPrivate.InputContext.prototype.mode;
 
 /** @type {chrome.inputMethodPrivate.InputContextType} */
 chrome.inputMethodPrivate.InputContext.prototype.type;
diff --git a/third_party/libavif/BUILD.gn b/third_party/libavif/BUILD.gn
index 85e065c..1430038 100644
--- a/third_party/libavif/BUILD.gn
+++ b/third_party/libavif/BUILD.gn
@@ -10,6 +10,7 @@
     "src/src/avif.c",
     "src/src/codec_dav1d.c",
     "src/src/colr.c",
+    "src/src/io.c",
     "src/src/mem.c",
     "src/src/obu.c",
     "src/src/rawdata.c",
diff --git a/third_party/libxml/README.chromium b/third_party/libxml/README.chromium
index 638320e..f84cc64 100644
--- a/third_party/libxml/README.chromium
+++ b/third_party/libxml/README.chromium
@@ -1,6 +1,6 @@
 Name: libxml
 URL: http://xmlsoft.org
-Version: e4fb36841800038c289997432ca547c9bfef9db1
+Version: 0b3c64d9f2f3e9ce1a98d8f19ee7a763c87e27d5
 CPEPrefix: cpe:/a:xmlsoft:libxml2:2.9.9
 License: MIT
 License File: src/Copyright
@@ -22,8 +22,8 @@
 - chromium-issue-708434.patch: Guard against input counter overflow.
 - revert-non-recursive-xml-parsing.patch: Making parts of the XML parser
     non-recursive broke a few web platform tests.
-- add-missing-ifdef-in-xml-reader.patch: Bug fix forgot to guard functionality
-    with appropriate #ifdef.
+- add-fuzz-target.patch: Prevents autoreconf from failing on mac due to a
+    missing makefile for fuzz.
 - Add helper classes in the chromium/ subdirectory.
 - Delete various unused files, see chromium/roll.py
 
diff --git a/third_party/libxml/chromium/add-fuzz-target.patch b/third_party/libxml/chromium/add-fuzz-target.patch
new file mode 100644
index 0000000..420d5c7b
--- /dev/null
+++ b/third_party/libxml/chromium/add-fuzz-target.patch
@@ -0,0 +1,13 @@
+diff --git a/Makefile.am b/Makefile.am
+index 76a834ef..4ef0eb92 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -4,7 +4,7 @@ ACLOCAL_AMFLAGS = -I m4
+ 
+ SUBDIRS = include . doc example fuzz xstc $(PYTHON_SUBDIR)
+ 
+-DIST_SUBDIRS = include . doc example python xstc
++DIST_SUBDIRS = include . doc example python xstc fuzz
+ 
+ AM_CPPFLAGS = -I$(top_builddir)/include -I$(srcdir)/include
+ 
diff --git a/third_party/libxml/chromium/add-missing-ifdef-in-xml-reader.patch b/third_party/libxml/chromium/add-missing-ifdef-in-xml-reader.patch
deleted file mode 100644
index 17cd15a..0000000
--- a/third_party/libxml/chromium/add-missing-ifdef-in-xml-reader.patch
+++ /dev/null
@@ -1,13 +0,0 @@
---- a/xmlreader.c
-+++ b/xmlreader.c
-@@ -2262,8 +2262,10 @@ xmlFreeTextReader(xmlTextReaderPtr reader) {
- 	    reader->dict = NULL;
- 	if ((reader->ctxt->vctxt.vstateTab != NULL) &&
- 	    (reader->ctxt->vctxt.vstateMax > 0)){
-+#ifdef LIBXML_REGEXP_ENABLED
-             while (reader->ctxt->vctxt.vstateNr > 0)
-                 xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL);
-+#endif /* LIBXML_REGEXP_ENABLED */
- 	    xmlFree(reader->ctxt->vctxt.vstateTab);
- 	    reader->ctxt->vctxt.vstateTab = NULL;
- 	    reader->ctxt->vctxt.vstateMax = 0;
diff --git a/third_party/libxml/chromium/roll.py b/third_party/libxml/chromium/roll.py
index a75c3bb..1c5f58a 100755
--- a/third_party/libxml/chromium/roll.py
+++ b/third_party/libxml/chromium/roll.py
@@ -34,12 +34,6 @@
 # 3. On Mac, install these packages with brew:
 #      autoconf automake libtool pkgconfig icu4c
 #
-#    Important! Before running roll.py, set these environmental variables so the
-#    configure script can find ICU:
-#      export LDFLAGS="-L/path/to/homebrew/opt/icu4c/lib"
-#      export CPPFLAGS="-I/path/to/homebrew/opt/icu4c/include"
-#      export PKG_CONFIG_PATH="/path/to/homebrew/opt/icu4c/lib/pkgconfig"
-#
 # Procedure:
 #
 # Warning: This process is destructive. Run it on a clean branch.
@@ -66,7 +60,7 @@
 #
 # 3. On Mac, in the Chromium src directory:
 #    a. git cl patch <Gerrit Issue ID>
-#    b. third_party/libxml/chromium/roll.py --mac
+#    b. third_party/libxml/chromium/roll.py --mac --icu4c_path=~/homebrew/opt/icu4c
 #    c. Make and commit any final changes to README.chromium, BUILD.gn, etc.
 #    d. git cl upload
 #    e. Complete the review as usual
@@ -78,8 +72,8 @@
     'chromium-issue-628581.patch',
     'libxml2-2.9.4-security-xpath-nodetab-uaf.patch',
     'chromium-issue-708434.patch',
-    # TODO(dcheng): Merge this back upstream.
-    'add-missing-ifdef-in-xml-reader.patch',
+    # TODO(jarhar): Merge this back upstream.
+    'add-fuzz-target.patch',
 ]
 
 
@@ -405,7 +399,7 @@
                 XML_WIN32_CONFIGURE_OPTIONS)
 
             # Add and commit the result.
-            shutil.move('VC10/config.h', '../../win32/config.h')
+            shutil.move('../config.h', '../../win32/config.h')
             git('add', '../../win32/config.h')
             shutil.move('../include/libxml/xmlversion.h',
                         '../../win32/include/libxml/xmlversion.h')
@@ -415,7 +409,12 @@
     print('Now push to Mac and run steps there.')
 
 
-def roll_libxml_mac(src_path):
+def roll_libxml_mac(src_path, icu4c_path):
+    icu4c_path = os.path.abspath(os.path.expanduser(icu4c_path))
+    os.environ["LDFLAGS"] = "-L" + os.path.join(icu4c_path, 'lib')
+    os.environ["CPPFLAGS"] = "-I" + os.path.join(icu4c_path, 'include')
+    os.environ["PKG_CONFIG_PATH"] = os.path.join(icu4c_path, 'lib/pkgconfig')
+
     full_path_to_third_party_libxml = os.path.join(
         src_path, THIRD_PARTY_LIBXML_SRC, '..')
 
@@ -459,6 +458,9 @@
         type=str,
         nargs='?',
         help='The path to the local clone of the libxml2 git repo.')
+    parser.add_argument(
+        '--icu4c_path',
+        help='The path to the homebrew installation of icu4c.')
     args = parser.parse_args()
 
     if args.linux:
@@ -471,7 +473,12 @@
     elif args.win32:
         roll_libxml_win32(src_dir)
     elif args.mac:
-        roll_libxml_mac(src_dir)
+        icu4c_path = args.icu4c_path
+        if not icu4c_path:
+            print('Specify the path to the homebrew installation of icu4c with --icu4c_path.')
+            print('  ex: roll.py --mac --icu4c_path=~/homebrew/opt/icu4c')
+            sys.exit(1)
+        roll_libxml_mac(src_dir, icu4c_path)
 
 
 if __name__ == '__main__':
diff --git a/third_party/libxml/linux/config.h b/third_party/libxml/linux/config.h
index e334240..b6ae433e 100644
--- a/third_party/libxml/linux/config.h
+++ b/third_party/libxml/linux/config.h
@@ -1,6 +1,9 @@
 /* config.h.  Generated from config.h.in by configure.  */
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* A form that will not confuse apibuild.py */
+#define ATTRIBUTE_DESTRUCTOR __attribute__((destructor))
+
 /* Type cast for the gethostbyname() argument */
 #define GETHOSTBYNAME_ARG_CAST /**/
 
@@ -10,6 +13,9 @@
 /* Define to 1 if you have the <arpa/nameser.h> header file. */
 #define HAVE_ARPA_NAMESER_H 1
 
+/* Define if __attribute__((destructor)) is accepted */
+#define HAVE_ATTRIBUTE_DESTRUCTOR 1
+
 /* Whether struct sockaddr::__ss_family exists */
 /* #undef HAVE_BROKEN_SS_FAMILY */
 
@@ -240,19 +246,19 @@
 #define PACKAGE_BUGREPORT ""
 
 /* Define to the full name of this package. */
-#define PACKAGE_NAME ""
+#define PACKAGE_NAME "libxml2"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
+#define PACKAGE_STRING "libxml2 2.9.10"
 
 /* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
+#define PACKAGE_TARNAME "libxml2"
 
 /* Define to the home page for this package. */
 #define PACKAGE_URL ""
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION ""
+#define PACKAGE_VERSION "2.9.10"
 
 /* Type cast for the send() function 2nd arg */
 #define SEND_ARG2_CAST /**/
diff --git a/third_party/libxml/mac/config.h b/third_party/libxml/mac/config.h
index 16cd0ae..563202e1 100644
--- a/third_party/libxml/mac/config.h
+++ b/third_party/libxml/mac/config.h
@@ -1,6 +1,9 @@
 /* config.h.  Generated from config.h.in by configure.  */
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* A form that will not confuse apibuild.py */
+#define ATTRIBUTE_DESTRUCTOR __attribute__((destructor))
+
 /* Type cast for the gethostbyname() argument */
 #define GETHOSTBYNAME_ARG_CAST /**/
 
@@ -10,6 +13,9 @@
 /* Define to 1 if you have the <arpa/nameser.h> header file. */
 #define HAVE_ARPA_NAMESER_H 1
 
+/* Define if __attribute__((destructor)) is accepted */
+#define HAVE_ATTRIBUTE_DESTRUCTOR 1
+
 /* Whether struct sockaddr::__ss_family exists */
 /* #undef HAVE_BROKEN_SS_FAMILY */
 
@@ -240,19 +246,19 @@
 #define PACKAGE_BUGREPORT ""
 
 /* Define to the full name of this package. */
-#define PACKAGE_NAME ""
+#define PACKAGE_NAME "libxml2"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
+#define PACKAGE_STRING "libxml2 2.9.10"
 
 /* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
+#define PACKAGE_TARNAME "libxml2"
 
 /* Define to the home page for this package. */
 #define PACKAGE_URL ""
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION ""
+#define PACKAGE_VERSION "2.9.10"
 
 /* Type cast for the send() function 2nd arg */
 #define SEND_ARG2_CAST /**/
diff --git a/third_party/libxml/src/COPYING b/third_party/libxml/src/COPYING
deleted file mode 100644
index d61318502..0000000
--- a/third_party/libxml/src/COPYING
+++ /dev/null
@@ -1,23 +0,0 @@
-Except where otherwise noted in the source code (e.g. the files hash.c,
-list.c and the trio files, which are covered by a similar licence but
-with different Copyright notices) all the files are:
-
- Copyright (C) 1998-2012 Daniel Veillard.  All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is fur-
-nished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
-NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/third_party/libxml/src/HTMLparser.c b/third_party/libxml/src/HTMLparser.c
index 5dd62df..de624f8d 100644
--- a/third_party/libxml/src/HTMLparser.c
+++ b/third_party/libxml/src/HTMLparser.c
@@ -296,7 +296,7 @@
 
 #define UPPER (toupper(*ctxt->input->cur))
 
-#define SKIP(val) ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val)
+#define SKIP(val) ctxt->input->cur += (val),ctxt->input->col+=(val)
 
 #define NXT(val) ctxt->input->cur[(val)]
 
@@ -330,7 +330,7 @@
     if (*(ctxt->input->cur) == '\n') {					\
 	ctxt->input->line++; ctxt->input->col = 1;			\
     } else ctxt->input->col++;						\
-    ctxt->token = 0; ctxt->input->cur += l; ctxt->nbChars++;		\
+    ctxt->token = 0; ctxt->input->cur += l;				\
   } while (0)
 
 /************
@@ -414,6 +414,10 @@
 
 static int
 htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
+    const unsigned char *cur;
+    unsigned char c;
+    unsigned int val;
+
     if (ctxt->instate == XML_PARSER_EOF)
 	return(0);
 
@@ -421,99 +425,29 @@
 	*len = 0;
 	return(ctxt->token);
     }
-    if (ctxt->charset == XML_CHAR_ENCODING_UTF8) {
-	/*
-	 * We are supposed to handle UTF8, check it's valid
-	 * From rfc2044: encoding of the Unicode values on UTF-8:
-	 *
-	 * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
-	 * 0000 0000-0000 007F   0xxxxxxx
-	 * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
-	 * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
-	 *
-	 * Check for the 0x110000 limit too
-	 */
-	const unsigned char *cur = ctxt->input->cur;
-	unsigned char c;
-	unsigned int val;
-
-	c = *cur;
-	if (c & 0x80) {
-	    if (cur[1] == 0) {
-		xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-                cur = ctxt->input->cur;
-            }
-	    if ((cur[1] & 0xc0) != 0x80)
-		goto encoding_error;
-	    if ((c & 0xe0) == 0xe0) {
-
-		if (cur[2] == 0) {
-		    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-                    cur = ctxt->input->cur;
-                }
-		if ((cur[2] & 0xc0) != 0x80)
-		    goto encoding_error;
-		if ((c & 0xf0) == 0xf0) {
-		    if (cur[3] == 0) {
-			xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
-                        cur = ctxt->input->cur;
-                    }
-		    if (((c & 0xf8) != 0xf0) ||
-			((cur[3] & 0xc0) != 0x80))
-			goto encoding_error;
-		    /* 4-byte code */
-		    *len = 4;
-		    val = (cur[0] & 0x7) << 18;
-		    val |= (cur[1] & 0x3f) << 12;
-		    val |= (cur[2] & 0x3f) << 6;
-		    val |= cur[3] & 0x3f;
-		} else {
-		  /* 3-byte code */
-		    *len = 3;
-		    val = (cur[0] & 0xf) << 12;
-		    val |= (cur[1] & 0x3f) << 6;
-		    val |= cur[2] & 0x3f;
-		}
-	    } else {
-	      /* 2-byte code */
-		*len = 2;
-		val = (cur[0] & 0x1f) << 6;
-		val |= cur[1] & 0x3f;
-	    }
-	    if (!IS_CHAR(val)) {
-	        htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
-				"Char 0x%X out of allowed range\n", val);
-	    }
-	    return(val);
-	} else {
-            if ((*ctxt->input->cur == 0) &&
-                (ctxt->input->cur < ctxt->input->end)) {
-                    htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
-				"Char 0x%X out of allowed range\n", 0);
-                *len = 1;
-                return(' ');
-            }
-	    /* 1-byte code */
-	    *len = 1;
-	    return((int) *ctxt->input->cur);
-	}
-    }
-    /*
-     * Assume it's a fixed length encoding (1) with
-     * a compatible encoding for the ASCII set, since
-     * XML constructs only use < 128 chars
-     */
-    *len = 1;
-    if ((int) *ctxt->input->cur < 0x80)
-	return((int) *ctxt->input->cur);
-
-    /*
-     * Humm this is bad, do an automatic flow conversion
-     */
-    {
+    if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
         xmlChar * guess;
         xmlCharEncodingHandlerPtr handler;
 
+        /*
+         * Assume it's a fixed length encoding (1) with
+         * a compatible encoding for the ASCII set, since
+         * HTML constructs only use < 128 chars
+         */
+        if ((int) *ctxt->input->cur < 0x80) {
+            *len = 1;
+            if ((*ctxt->input->cur == 0) &&
+                (ctxt->input->cur < ctxt->input->end)) {
+                htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+                                "Char 0x%X out of allowed range\n", 0);
+                return(' ');
+            }
+            return((int) *ctxt->input->cur);
+        }
+
+        /*
+         * Humm this is bad, do an automatic flow conversion
+         */
         guess = htmlFindEncoding(ctxt);
         if (guess == NULL) {
             xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1);
@@ -532,7 +466,86 @@
         ctxt->charset = XML_CHAR_ENCODING_UTF8;
     }
 
-    return(xmlCurrentChar(ctxt, len));
+    /*
+     * We are supposed to handle UTF8, check it's valid
+     * From rfc2044: encoding of the Unicode values on UTF-8:
+     *
+     * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
+     * 0000 0000-0000 007F   0xxxxxxx
+     * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
+     * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
+     *
+     * Check for the 0x110000 limit too
+     */
+    cur = ctxt->input->cur;
+    c = *cur;
+    if (c & 0x80) {
+        if ((c & 0x40) == 0)
+            goto encoding_error;
+        if (cur[1] == 0) {
+            xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+            cur = ctxt->input->cur;
+        }
+        if ((cur[1] & 0xc0) != 0x80)
+            goto encoding_error;
+        if ((c & 0xe0) == 0xe0) {
+
+            if (cur[2] == 0) {
+                xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+                cur = ctxt->input->cur;
+            }
+            if ((cur[2] & 0xc0) != 0x80)
+                goto encoding_error;
+            if ((c & 0xf0) == 0xf0) {
+                if (cur[3] == 0) {
+                    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+                    cur = ctxt->input->cur;
+                }
+                if (((c & 0xf8) != 0xf0) ||
+                    ((cur[3] & 0xc0) != 0x80))
+                    goto encoding_error;
+                /* 4-byte code */
+                *len = 4;
+                val = (cur[0] & 0x7) << 18;
+                val |= (cur[1] & 0x3f) << 12;
+                val |= (cur[2] & 0x3f) << 6;
+                val |= cur[3] & 0x3f;
+                if (val < 0x10000)
+                    goto encoding_error;
+            } else {
+              /* 3-byte code */
+                *len = 3;
+                val = (cur[0] & 0xf) << 12;
+                val |= (cur[1] & 0x3f) << 6;
+                val |= cur[2] & 0x3f;
+                if (val < 0x800)
+                    goto encoding_error;
+            }
+        } else {
+          /* 2-byte code */
+            *len = 2;
+            val = (cur[0] & 0x1f) << 6;
+            val |= cur[1] & 0x3f;
+            if (val < 0x80)
+                goto encoding_error;
+        }
+        if (!IS_CHAR(val)) {
+            htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+                            "Char 0x%X out of allowed range\n", val);
+        }
+        return(val);
+    } else {
+        if ((*ctxt->input->cur == 0) &&
+            (ctxt->input->cur < ctxt->input->end)) {
+            htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+                            "Char 0x%X out of allowed range\n", 0);
+            *len = 1;
+            return(' ');
+        }
+        /* 1-byte code */
+        *len = 1;
+        return((int) *ctxt->input->cur);
+    }
 
 encoding_error:
     /*
@@ -584,7 +597,6 @@
 		ctxt->input->line++; ctxt->input->col = 1;
 	    } else ctxt->input->col++;
 	    ctxt->input->cur++;
-	    ctxt->nbChars++;
 	    if (*ctxt->input->cur == 0)
 		xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
 	}
@@ -2482,7 +2494,6 @@
 	    count = in - ctxt->input->cur;
 	    ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
 	    ctxt->input->cur = in;
-	    ctxt->nbChars += count;
 	    ctxt->input->col += count;
 	    return(ret);
 	}
@@ -2789,47 +2800,39 @@
 static xmlChar *
 htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) {
     size_t len = 0, startPosition = 0;
+    int err = 0;
+    int quote;
     xmlChar *ret = NULL;
 
-    if (CUR == '"') {
-        NEXT;
-
-        if (CUR_PTR < BASE_PTR)
-            return(ret);
-        startPosition = CUR_PTR - BASE_PTR;
-
-	while ((IS_CHAR_CH(CUR)) && (CUR != '"')) {
-	    NEXT;
-	    len++;
-	}
-	if (!IS_CHAR_CH(CUR)) {
-	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
-			 "Unfinished SystemLiteral\n", NULL, NULL);
-	} else {
-	    ret = xmlStrndup((BASE_PTR+startPosition), len);
-	    NEXT;
-        }
-    } else if (CUR == '\'') {
-        NEXT;
-
-        if (CUR_PTR < BASE_PTR)
-            return(ret);
-        startPosition = CUR_PTR - BASE_PTR;
-
-	while ((IS_CHAR_CH(CUR)) && (CUR != '\'')) {
-	    NEXT;
-	    len++;
-	}
-	if (!IS_CHAR_CH(CUR)) {
-	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
-			 "Unfinished SystemLiteral\n", NULL, NULL);
-	} else {
-	    ret = xmlStrndup((BASE_PTR+startPosition), len);
-	    NEXT;
-        }
-    } else {
+    if ((CUR != '"') && (CUR != '\'')) {
 	htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_STARTED,
-	             " or ' expected\n", NULL, NULL);
+	             "SystemLiteral \" or ' expected\n", NULL, NULL);
+        return(NULL);
+    }
+    quote = CUR;
+    NEXT;
+
+    if (CUR_PTR < BASE_PTR)
+        return(ret);
+    startPosition = CUR_PTR - BASE_PTR;
+
+    while ((CUR != 0) && (CUR != quote)) {
+        /* TODO: Handle UTF-8 */
+        if (!IS_CHAR_CH(CUR)) {
+            htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+                            "Invalid char in SystemLiteral 0x%X\n", CUR);
+            err = 1;
+        }
+        NEXT;
+        len++;
+    }
+    if (CUR != quote) {
+        htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
+                     "Unfinished SystemLiteral\n", NULL, NULL);
+    } else {
+        NEXT;
+        if (err == 0)
+            ret = xmlStrndup((BASE_PTR+startPosition), len);
     }
 
     return(ret);
@@ -2849,51 +2852,42 @@
 static xmlChar *
 htmlParsePubidLiteral(htmlParserCtxtPtr ctxt) {
     size_t len = 0, startPosition = 0;
+    int err = 0;
+    int quote;
     xmlChar *ret = NULL;
+
+    if ((CUR != '"') && (CUR != '\'')) {
+	htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_STARTED,
+	             "PubidLiteral \" or ' expected\n", NULL, NULL);
+        return(NULL);
+    }
+    quote = CUR;
+    NEXT;
+
     /*
      * Name ::= (Letter | '_') (NameChar)*
      */
-    if (CUR == '"') {
-        NEXT;
+    if (CUR_PTR < BASE_PTR)
+        return(ret);
+    startPosition = CUR_PTR - BASE_PTR;
 
-        if (CUR_PTR < BASE_PTR)
-            return(ret);
-        startPosition = CUR_PTR - BASE_PTR;
-
-        while (IS_PUBIDCHAR_CH(CUR)) {
-            len++;
-            NEXT;
+    while ((CUR != 0) && (CUR != quote)) {
+        if (!IS_PUBIDCHAR_CH(CUR)) {
+            htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+                            "Invalid char in PubidLiteral 0x%X\n", CUR);
+            err = 1;
         }
-
-	if (CUR != '"') {
-	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
-	                 "Unfinished PubidLiteral\n", NULL, NULL);
-	} else {
-	    ret = xmlStrndup((BASE_PTR + startPosition), len);
-	    NEXT;
-	}
-    } else if (CUR == '\'') {
+        len++;
         NEXT;
+    }
 
-        if (CUR_PTR < BASE_PTR)
-            return(ret);
-        startPosition = CUR_PTR - BASE_PTR;
-
-        while ((IS_PUBIDCHAR_CH(CUR)) && (CUR != '\'')){
-            len++;
-            NEXT;
-        }
-
-	if (CUR != '\'') {
-	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
-	                 "Unfinished PubidLiteral\n", NULL, NULL);
-	} else {
-	    ret = xmlStrndup((BASE_PTR + startPosition), len);
-	    NEXT;
-	}
+    if (CUR != '"') {
+        htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
+                     "Unfinished PubidLiteral\n", NULL, NULL);
     } else {
-	htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_STARTED,
-	             "PubidLiteral \" or ' expected\n", NULL, NULL);
+        NEXT;
+        if (err == 0)
+            ret = xmlStrndup((BASE_PTR + startPosition), len);
     }
 
     return(ret);
@@ -2928,7 +2922,7 @@
 
     SHRINK;
     cur = CUR_CHAR(l);
-    while (IS_CHAR_CH(cur)) {
+    while (cur != 0) {
 	if ((cur == '<') && (NXT(1) == '/')) {
             /*
              * One should break here, the specification is clear:
@@ -2959,7 +2953,12 @@
                 }
             }
 	}
-	COPY_BUF(l,buf,nbchar,cur);
+        if (IS_CHAR(cur)) {
+	    COPY_BUF(l,buf,nbchar,cur);
+        } else {
+            htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+                            "Invalid char in CDATA 0x%X\n", cur);
+        }
 	if (nbchar >= HTML_PARSER_BIG_BUFFER_SIZE) {
             buf[nbchar] = 0;
 	    if (ctxt->sax->cdataBlock!= NULL) {
@@ -2977,14 +2976,6 @@
 	cur = CUR_CHAR(l);
     }
 
-    if ((!(IS_CHAR_CH(cur))) && (!((cur == 0) && (ctxt->progressive)))) {
-        htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
-                    "Invalid char in CDATA 0x%X\n", cur);
-        if (ctxt->input->cur < ctxt->input->end) {
-            NEXT;
-        }
-    }
-
     if ((nbchar != 0) && (ctxt->sax != NULL) && (!ctxt->disableSAX)) {
         buf[nbchar] = 0;
 	if (ctxt->sax->cdataBlock!= NULL) {
@@ -3232,7 +3223,7 @@
 	    }
             SKIP_BLANKS;
 	    cur = CUR_CHAR(l);
-	    while (IS_CHAR(cur) && (cur != '>')) {
+	    while ((cur != 0) && (cur != '>')) {
 		if (len + 5 >= size) {
 		    xmlChar *tmp;
 
@@ -3251,7 +3242,13 @@
 		    GROW;
 		    count = 0;
 		}
-		COPY_BUF(l,buf,len,cur);
+                if (IS_CHAR(cur)) {
+		    COPY_BUF(l,buf,len,cur);
+                } else {
+                    htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+                                    "Invalid char in processing instruction "
+                                    "0x%X\n", cur);
+                }
 		NEXTL(l);
 		cur = CUR_CHAR(l);
 		if (cur == 0) {
@@ -3321,15 +3318,15 @@
     len = 0;
     buf[len] = 0;
     q = CUR_CHAR(ql);
-    if (!IS_CHAR(q))
+    if (q == 0)
         goto unfinished;
     NEXTL(ql);
     r = CUR_CHAR(rl);
-    if (!IS_CHAR(r))
+    if (r == 0)
         goto unfinished;
     NEXTL(rl);
     cur = CUR_CHAR(l);
-    while (IS_CHAR(cur) &&
+    while ((cur != 0) &&
            ((cur != '>') ||
 	    (r != '-') || (q != '-'))) {
 	if (len + 5 >= size) {
@@ -3345,7 +3342,12 @@
 	    }
 	    buf = tmp;
 	}
-	COPY_BUF(ql,buf,len,q);
+        if (IS_CHAR(q)) {
+	    COPY_BUF(ql,buf,len,q);
+        } else {
+            htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+                            "Invalid char in comment 0x%X\n", q);
+        }
 	q = r;
 	ql = rl;
 	r = cur;
@@ -3359,7 +3361,7 @@
 	}
     }
     buf[len] = 0;
-    if (IS_CHAR(cur)) {
+    if (cur == '>') {
         NEXT;
 	if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
 	    (!ctxt->disableSAX))
@@ -3400,13 +3402,16 @@
         ((NXT(2) == 'x') || NXT(2) == 'X')) {
 	SKIP(3);
 	while (CUR != ';') {
-	    if ((CUR >= '0') && (CUR <= '9'))
-	        val = val * 16 + (CUR - '0');
-	    else if ((CUR >= 'a') && (CUR <= 'f'))
-	        val = val * 16 + (CUR - 'a') + 10;
-	    else if ((CUR >= 'A') && (CUR <= 'F'))
-	        val = val * 16 + (CUR - 'A') + 10;
-	    else {
+	    if ((CUR >= '0') && (CUR <= '9')) {
+                if (val < 0x110000)
+	            val = val * 16 + (CUR - '0');
+            } else if ((CUR >= 'a') && (CUR <= 'f')) {
+                if (val < 0x110000)
+	            val = val * 16 + (CUR - 'a') + 10;
+            } else if ((CUR >= 'A') && (CUR <= 'F')) {
+                if (val < 0x110000)
+	            val = val * 16 + (CUR - 'A') + 10;
+            } else {
 	        htmlParseErr(ctxt, XML_ERR_INVALID_HEX_CHARREF,
 		             "htmlParseCharRef: missing semicolon\n",
 			     NULL, NULL);
@@ -3419,9 +3424,10 @@
     } else if  ((CUR == '&') && (NXT(1) == '#')) {
 	SKIP(2);
 	while (CUR != ';') {
-	    if ((CUR >= '0') && (CUR <= '9'))
-	        val = val * 10 + (CUR - '0');
-	    else {
+	    if ((CUR >= '0') && (CUR <= '9')) {
+                if (val < 0x110000)
+	            val = val * 10 + (CUR - '0');
+            } else {
 	        htmlParseErr(ctxt, XML_ERR_INVALID_DEC_CHARREF,
 		             "htmlParseCharRef: missing semicolon\n",
 			     NULL, NULL);
@@ -3440,6 +3446,9 @@
      */
     if (IS_CHAR(val)) {
         return(val);
+    } else if (val >= 0x110000) {
+	htmlParseErr(ctxt, XML_ERR_INVALID_CHAR,
+		     "htmlParseCharRef: value too large\n", NULL, NULL);
     } else {
 	htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
 			"htmlParseCharRef: invalid xmlChar value %d\n",
@@ -3499,9 +3508,12 @@
     if (CUR != '>') {
 	htmlParseErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED,
 	             "DOCTYPE improperly terminated\n", NULL, NULL);
-        /* We shouldn't try to resynchronize ... */
+        /* Ignore bogus content */
+        while ((CUR != 0) && (CUR != '>'))
+            NEXT;
     }
-    NEXT;
+    if (CUR == '>')
+        NEXT;
 
     /*
      * Create or update the document accordingly to the DOCTYPE
@@ -3779,7 +3791,7 @@
 
 
 	/* Dump the bogus tag like browsers do */
-	while ((IS_CHAR_CH(CUR)) && (CUR != '>') &&
+	while ((CUR != 0) && (CUR != '>') &&
                (ctxt->instate != XML_PARSER_EOF))
 	    NEXT;
         return -1;
@@ -3835,11 +3847,9 @@
      * (S Attribute)* S?
      */
     SKIP_BLANKS;
-    while ((IS_CHAR_CH(CUR)) &&
+    while ((CUR != 0) &&
            (CUR != '>') &&
 	   ((CUR != '/') || (NXT(1) != '>'))) {
-	long cons = ctxt->nbChars;
-
 	GROW;
 	attname = htmlParseAttribute(ctxt, &attvalue);
         if (attname != NULL) {
@@ -3898,7 +3908,7 @@
 	        xmlFree(attvalue);
 	    /* Dump the bogus attribute string up to the next blank or
 	     * the end of the tag. */
-	    while ((IS_CHAR_CH(CUR)) &&
+	    while ((CUR != 0) &&
 	           !(IS_BLANK_CH(CUR)) && (CUR != '>') &&
 		   ((CUR != '/') || (NXT(1) != '>')))
 		NEXT;
@@ -3906,12 +3916,6 @@
 
 failed:
 	SKIP_BLANKS;
-        if (cons == ctxt->nbChars) {
-	    htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-	                 "htmlParseStartTag: problem parsing attributes\n",
-			 NULL, NULL);
-	    break;
-	}
     }
 
     /*
@@ -3979,19 +3983,14 @@
      * We should definitely be at the ending "S? '>'" part
      */
     SKIP_BLANKS;
-    if ((!IS_CHAR_CH(CUR)) || (CUR != '>')) {
+    if (CUR != '>') {
         htmlParseErr(ctxt, XML_ERR_GT_REQUIRED,
 	             "End tag : expected '>'\n", NULL, NULL);
-	if (ctxt->recovery) {
-	    /*
-	     * We're not at the ending > !!
-	     * Error, unless in recover mode where we search forwards
-	     * until we find a >
-	     */
-	    while (CUR != '\0' && CUR != '>') NEXT;
-	    NEXT;
-	}
-    } else
+        /* Skip to next '>' */
+        while ((CUR != 0) && (CUR != '>'))
+            NEXT;
+    }
+    if (CUR == '>')
         NEXT;
 
     /*
@@ -4152,8 +4151,6 @@
     currentNode = xmlStrdup(ctxt->name);
     depth = ctxt->nameNr;
     while (1) {
-	long cons = ctxt->nbChars;
-
         GROW;
 
         if (ctxt->instate == XML_PARSER_EOF)
@@ -4181,7 +4178,7 @@
 			 "htmlParseStartTag: invalid element name\n",
 			 NULL, NULL);
 	        /* Dump the bogus tag like browsers do */
-        while ((IS_CHAR_CH(CUR)) && (CUR != '>'))
+                while ((CUR != 0) && (CUR != '>'))
 	            NEXT;
 
 	        if (currentNode != NULL)
@@ -4273,15 +4270,6 @@
 	    else {
 		htmlParseCharData(ctxt);
 	    }
-
-	    if (cons == ctxt->nbChars) {
-		if (ctxt->node != NULL) {
-		    htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-		                 "detected an error in element content\n",
-				 NULL, NULL);
-		}
-		break;
-	    }
 	}
         GROW;
     }
@@ -4396,7 +4384,7 @@
      */
     currentNode = xmlStrdup(ctxt->name);
     depth = ctxt->nameNr;
-    while (IS_CHAR_CH(CUR)) {
+    while (CUR != 0) {
 	oldptr = ctxt->input->cur;
 	htmlParseContent(ctxt);
 	if (oldptr==ctxt->input->cur) break;
@@ -4413,7 +4401,7 @@
        node_info.node = ctxt->node;
        xmlParserAddNodeInfo(ctxt, &node_info);
     }
-    if (!IS_CHAR_CH(CUR)) {
+    if (CUR == 0) {
 	htmlAutoCloseOnEnd(ctxt);
     }
 
@@ -4434,7 +4422,7 @@
        xmlParserAddNodeInfo(ctxt, ctxt->nodeInfo);
        htmlNodeInfoPop(ctxt);
     }
-    if (!IS_CHAR_CH(CUR)) {
+    if (CUR == 0) {
        htmlAutoCloseOnEnd(ctxt);
     }
 }
@@ -4552,8 +4540,6 @@
     currentNode = xmlStrdup(ctxt->name);
     depth = ctxt->nameNr;
     while (1) {
-	long cons = ctxt->nbChars;
-
         GROW;
 
         if (ctxt->instate == XML_PARSER_EOF)
@@ -4583,7 +4569,7 @@
 			 "htmlParseStartTag: invalid element name\n",
 			 NULL, NULL);
 	        /* Dump the bogus tag like browsers do */
-	        while ((IS_CHAR_CH(CUR)) && (CUR != '>'))
+	        while ((CUR == 0) && (CUR != '>'))
 	            NEXT;
 
 	        htmlParserFinishElementParsing(ctxt);
@@ -4687,15 +4673,6 @@
 	    else {
 		htmlParseCharData(ctxt);
 	    }
-
-	    if (cons == ctxt->nbChars) {
-		if (ctxt->node != NULL) {
-		    htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-		                 "detected an error in element content\n",
-				 NULL, NULL);
-		}
-		break;
-	    }
 	}
         GROW;
     }
@@ -4959,7 +4936,6 @@
     ctxt->vctxt.warning = xmlParserValidityWarning;
     ctxt->record_info = 0;
     ctxt->validate = 0;
-    ctxt->nbChars = 0;
     ctxt->checkIndex = 0;
     ctxt->catalogs = NULL;
     xmlInitNodeInfoSeq(&ctxt->node_seq);
@@ -5119,7 +5095,7 @@
  * @first:  the first char to lookup
  * @next:  the next char to lookup or zero
  * @third:  the next char to lookup or zero
- * @comment: flag to force checking inside comments
+ * @ignoreattrval: skip over attribute values
  *
  * Try to find if a sequence (first, next, third) or  just (first next) or
  * (first) is available in the input stream.
@@ -5133,13 +5109,11 @@
  */
 static int
 htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
-                        xmlChar next, xmlChar third, int iscomment,
-                        int ignoreattrval)
+                        xmlChar next, xmlChar third, int ignoreattrval)
 {
     int base, len;
     htmlParserInputPtr in;
     const xmlChar *buf;
-    int incomment = 0;
     int invalue = 0;
     char valdellim = 0x0;
 
@@ -5151,8 +5125,11 @@
     if (base < 0)
         return (-1);
 
-    if (ctxt->checkIndex > base)
+    if (ctxt->checkIndex > base) {
         base = ctxt->checkIndex;
+        /* Abuse hasPErefs member to restore current state. */
+        invalue = ctxt->hasPErefs & 1 ? 1 : 0;
+    }
 
     if (in->buf == NULL) {
         buf = in->base;
@@ -5168,14 +5145,6 @@
     else if (next)
         len--;
     for (; base < len; base++) {
-        if ((!incomment) && (base + 4 < len) && (!iscomment)) {
-            if ((buf[base] == '<') && (buf[base + 1] == '!') &&
-                (buf[base + 2] == '-') && (buf[base + 3] == '-')) {
-                incomment = 1;
-                /* do not increment past <! - some people use <!--> */
-                base += 2;
-            }
-        }
         if (ignoreattrval) {
             if (buf[base] == '"' || buf[base] == '\'') {
                 if (invalue) {
@@ -5192,16 +5161,6 @@
                 continue;
             }
         }
-        if (incomment) {
-            if (base + 3 > len)
-                return (-1);
-            if ((buf[base] == '-') && (buf[base + 1] == '-') &&
-                (buf[base + 2] == '>')) {
-                incomment = 0;
-                base += 2;
-            }
-            continue;
-        }
         if (buf[base] == first) {
             if (third != 0) {
                 if ((buf[base + 1] != next) || (buf[base + 2] != third))
@@ -5228,8 +5187,12 @@
             return (base - (in->cur - in->base));
         }
     }
-    if ((!incomment) && (!invalue))
-        ctxt->checkIndex = base;
+    ctxt->checkIndex = base;
+    /* Abuse hasPErefs member to track current state. */
+    if (invalue)
+        ctxt->hasPErefs |= 1;
+    else
+        ctxt->hasPErefs &= ~1;
 #ifdef DEBUG_PUSH
     if (next == 0)
         xmlGenericError(xmlGenericErrorContext,
@@ -5246,80 +5209,6 @@
 }
 
 /**
- * htmlParseLookupChars:
- * @ctxt: an HTML parser context
- * @stop: Array of chars, which stop the lookup.
- * @stopLen: Length of stop-Array
- *
- * Try to find if any char of the stop-Array is available in the input
- * stream.
- * This function has a side effect of (possibly) incrementing ctxt->checkIndex
- * to avoid rescanning sequences of bytes, it DOES change the state of the
- * parser, do not use liberally.
- *
- * Returns the index to the current parsing point if a stopChar
- *      is available, -1 otherwise.
- */
-static int
-htmlParseLookupChars(htmlParserCtxtPtr ctxt, const xmlChar * stop,
-                     int stopLen)
-{
-    int base, len;
-    htmlParserInputPtr in;
-    const xmlChar *buf;
-    int incomment = 0;
-    int i;
-
-    in = ctxt->input;
-    if (in == NULL)
-        return (-1);
-
-    base = in->cur - in->base;
-    if (base < 0)
-        return (-1);
-
-    if (ctxt->checkIndex > base)
-        base = ctxt->checkIndex;
-
-    if (in->buf == NULL) {
-        buf = in->base;
-        len = in->length;
-    } else {
-        buf = xmlBufContent(in->buf->buffer);
-        len = xmlBufUse(in->buf->buffer);
-    }
-
-    for (; base < len; base++) {
-        if (!incomment && (base + 4 < len)) {
-            if ((buf[base] == '<') && (buf[base + 1] == '!') &&
-                (buf[base + 2] == '-') && (buf[base + 3] == '-')) {
-                incomment = 1;
-                /* do not increment past <! - some people use <!--> */
-                base += 2;
-            }
-        }
-        if (incomment) {
-            if (base + 3 > len)
-                return (-1);
-            if ((buf[base] == '-') && (buf[base + 1] == '-') &&
-                (buf[base + 2] == '>')) {
-                incomment = 0;
-                base += 2;
-            }
-            continue;
-        }
-        for (i = 0; i < stopLen; ++i) {
-            if (buf[base] == stop[i]) {
-                ctxt->checkIndex = 0;
-                return (base - (in->cur - in->base));
-            }
-        }
-    }
-    ctxt->checkIndex = base;
-    return (-1);
-}
-
-/**
  * htmlParseTryOrFinish:
  * @ctxt:  an HTML parser context
  * @terminate:  last chunk indicator
@@ -5332,7 +5221,7 @@
 htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
     int ret = 0;
     htmlParserInputPtr in;
-    int avail = 0;
+    ptrdiff_t avail = 0;
     xmlChar cur, next;
 
     htmlParserNodeInfo node_info;
@@ -5397,7 +5286,8 @@
 	if (in->buf == NULL)
 	    avail = in->length - (in->cur - in->base);
 	else
-	    avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base);
+	    avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
+                    (in->cur - in->base);
 	if ((avail == 0) && (terminate)) {
 	    htmlAutoCloseOnEnd(ctxt);
 	    if ((ctxt->nameNr == 0) && (ctxt->instate != XML_PARSER_EOF)) {
@@ -5411,6 +5301,12 @@
 	}
         if (avail < 1)
 	    goto done;
+        /*
+         * This is done to make progress and avoid an infinite loop
+         * if a parsing attempt was aborted by hitting a NUL byte. After
+         * changing htmlCurrentChar, this probably isn't necessary anymore.
+         * We should consider removing this check.
+         */
 	cur = in->cur[0];
 	if (cur == 0) {
 	    SKIP(1);
@@ -5433,7 +5329,8 @@
 		    if (in->buf == NULL)
 			avail = in->length - (in->cur - in->base);
 		    else
-			avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base);
+			avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
+                                (in->cur - in->base);
 		}
 		if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
 		    ctxt->sax->setDocumentLocator(ctxt->userData,
@@ -5450,7 +5347,7 @@
 		    (UPP(6) == 'Y') && (UPP(7) == 'P') &&
 		    (UPP(8) == 'E')) {
 		    if ((!terminate) &&
-		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
 			goto done;
 #ifdef DEBUG_PUSH
 		    xmlGenericError(xmlGenericErrorContext,
@@ -5475,7 +5372,8 @@
 		if (in->buf == NULL)
 		    avail = in->length - (in->cur - in->base);
 		else
-		    avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base);
+		    avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
+                            (in->cur - in->base);
 		/*
 		 * no chars in buffer
 		 */
@@ -5496,7 +5394,7 @@
 	        if ((cur == '<') && (next == '!') &&
 		    (in->cur[2] == '-') && (in->cur[3] == '-')) {
 		    if ((!terminate) &&
-		        (htmlParseLookupSequence(ctxt, '-', '-', '>', 1, 1) < 0))
+		        (htmlParseLookupSequence(ctxt, '-', '-', '>', 0) < 0))
 			goto done;
 #ifdef DEBUG_PUSH
 		    xmlGenericError(xmlGenericErrorContext,
@@ -5506,7 +5404,7 @@
 		    ctxt->instate = XML_PARSER_MISC;
 	        } else if ((cur == '<') && (next == '?')) {
 		    if ((!terminate) &&
-		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
 			goto done;
 #ifdef DEBUG_PUSH
 		    xmlGenericError(xmlGenericErrorContext,
@@ -5520,7 +5418,7 @@
 		    (UPP(6) == 'Y') && (UPP(7) == 'P') &&
 		    (UPP(8) == 'E')) {
 		    if ((!terminate) &&
-		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
 			goto done;
 #ifdef DEBUG_PUSH
 		    xmlGenericError(xmlGenericErrorContext,
@@ -5536,7 +5434,7 @@
 		           (avail < 9)) {
 		    goto done;
 		} else {
-		    ctxt->instate = XML_PARSER_START_TAG;
+		    ctxt->instate = XML_PARSER_CONTENT;
 #ifdef DEBUG_PUSH
 		    xmlGenericError(xmlGenericErrorContext,
 			    "HPP: entering START_TAG\n");
@@ -5548,7 +5446,8 @@
 		if (in->buf == NULL)
 		    avail = in->length - (in->cur - in->base);
 		else
-		    avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base);
+		    avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
+                            (in->cur - in->base);
 		if (avail < 2)
 		    goto done;
 		cur = in->cur[0];
@@ -5556,7 +5455,7 @@
 		if ((cur == '<') && (next == '!') &&
 		    (in->cur[2] == '-') && (in->cur[3] == '-')) {
 		    if ((!terminate) &&
-		        (htmlParseLookupSequence(ctxt, '-', '-', '>', 1, 1) < 0))
+		        (htmlParseLookupSequence(ctxt, '-', '-', '>', 0) < 0))
 			goto done;
 #ifdef DEBUG_PUSH
 		    xmlGenericError(xmlGenericErrorContext,
@@ -5566,7 +5465,7 @@
 		    ctxt->instate = XML_PARSER_PROLOG;
 	        } else if ((cur == '<') && (next == '?')) {
 		    if ((!terminate) &&
-		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
 			goto done;
 #ifdef DEBUG_PUSH
 		    xmlGenericError(xmlGenericErrorContext,
@@ -5578,7 +5477,7 @@
 		           (avail < 4)) {
 		    goto done;
 		} else {
-		    ctxt->instate = XML_PARSER_START_TAG;
+		    ctxt->instate = XML_PARSER_CONTENT;
 #ifdef DEBUG_PUSH
 		    xmlGenericError(xmlGenericErrorContext,
 			    "HPP: entering START_TAG\n");
@@ -5589,7 +5488,8 @@
 		if (in->buf == NULL)
 		    avail = in->length - (in->cur - in->base);
 		else
-		    avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base);
+		    avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
+                            (in->cur - in->base);
 		if (avail < 1)
 		    goto done;
 		cur = in->cur[0];
@@ -5603,7 +5503,7 @@
 	        if ((cur == '<') && (next == '!') &&
 		    (in->cur[2] == '-') && (in->cur[3] == '-')) {
 		    if ((!terminate) &&
-		        (htmlParseLookupSequence(ctxt, '-', '-', '>', 1, 1) < 0))
+		        (htmlParseLookupSequence(ctxt, '-', '-', '>', 0) < 0))
 			goto done;
 #ifdef DEBUG_PUSH
 		    xmlGenericError(xmlGenericErrorContext,
@@ -5613,7 +5513,7 @@
 		    ctxt->instate = XML_PARSER_EPILOG;
 	        } else if ((cur == '<') && (next == '?')) {
 		    if ((!terminate) &&
-		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+		        (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
 			goto done;
 #ifdef DEBUG_PUSH
 		    xmlGenericError(xmlGenericErrorContext,
@@ -5677,7 +5577,7 @@
 		    break;
 		}
 		if ((!terminate) &&
-		    (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+		    (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
 		    goto done;
 
                 /* Capture start position */
@@ -5769,7 +5669,6 @@
 	    }
             case XML_PARSER_CONTENT: {
 		xmlChar chr[2] = { 0, 0 };
-		long cons;
 
                 /*
 		 * Handle preparsed entities and charRef
@@ -5814,7 +5713,6 @@
 		    goto done;
 		cur = in->cur[0];
 		next = in->cur[1];
-		cons = ctxt->nbChars;
 		if ((xmlStrEqual(ctxt->name, BAD_CAST"script")) ||
 		    (xmlStrEqual(ctxt->name, BAD_CAST"style"))) {
 		    /*
@@ -5824,7 +5722,7 @@
 		        int idx;
 			xmlChar val;
 
-			idx = htmlParseLookupSequence(ctxt, '<', '/', 0, 0, 0);
+			idx = htmlParseLookupSequence(ctxt, '<', '/', 0, 0);
 			if (idx < 0)
 			    goto done;
 		        val = in->cur[idx + 2];
@@ -5851,7 +5749,7 @@
 			(UPP(6) == 'Y') && (UPP(7) == 'P') &&
 			(UPP(8) == 'E')) {
 			if ((!terminate) &&
-			    (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+			    (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
 			    goto done;
 			htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR,
 			             "Misplaced DOCTYPE declaration\n",
@@ -5861,7 +5759,7 @@
 			(in->cur[2] == '-') && (in->cur[3] == '-')) {
 			if ((!terminate) &&
 			    (htmlParseLookupSequence(
-				ctxt, '-', '-', '>', 1, 1) < 0))
+				ctxt, '-', '-', '>', 0) < 0))
 			    goto done;
 #ifdef DEBUG_PUSH
 			xmlGenericError(xmlGenericErrorContext,
@@ -5871,7 +5769,7 @@
 			ctxt->instate = XML_PARSER_CONTENT;
 		    } else if ((cur == '<') && (next == '?')) {
 			if ((!terminate) &&
-			    (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+			    (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
 			    goto done;
 #ifdef DEBUG_PUSH
 			xmlGenericError(xmlGenericErrorContext,
@@ -5890,24 +5788,35 @@
 #endif
 			break;
 		    } else if (cur == '<') {
-			ctxt->instate = XML_PARSER_START_TAG;
-			ctxt->checkIndex = 0;
+                        if ((!terminate) && (next == 0))
+                            goto done;
+                        /*
+                         * Only switch to START_TAG if the next character
+                         * starts a valid name. Otherwise, htmlParseStartTag
+                         * might return without consuming all characters
+                         * up to the final '>'.
+                         */
+                        if ((IS_ASCII_LETTER(next)) ||
+                            (next == '_') || (next == ':') || (next == '.')) {
+                            ctxt->instate = XML_PARSER_START_TAG;
+                            ctxt->checkIndex = 0;
 #ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"HPP: entering START_TAG\n");
+                            xmlGenericError(xmlGenericErrorContext,
+                                    "HPP: entering START_TAG\n");
 #endif
+                        } else {
+                            htmlParseErr(ctxt, XML_ERR_NAME_REQUIRED,
+                                         "htmlParseTryOrFinish: "
+                                         "invalid element name\n",
+                                         NULL, NULL);
+                            htmlCheckParagraph(ctxt);
+                            if ((ctxt->sax != NULL) &&
+                                (ctxt->sax->characters != NULL))
+                                ctxt->sax->characters(ctxt->userData,
+                                                      in->cur, 1);
+                            NEXT;
+                        }
 			break;
-		    } else if (cur == '&') {
-			if ((!terminate) &&
-			    (htmlParseLookupChars(ctxt,
-                                                  BAD_CAST "; >/", 4) < 0))
-			    goto done;
-#ifdef DEBUG_PUSH
-			xmlGenericError(xmlGenericErrorContext,
-				"HPP: Parsing Reference\n");
-#endif
-			/* TODO: check generation of subtrees if noent !!! */
-			htmlParseReference(ctxt);
 		    } else {
 		        /*
 			 * check that the text sequence is complete
@@ -5916,25 +5825,23 @@
 			 * data detection.
 			 */
 			if ((!terminate) &&
-                            (htmlParseLookupChars(ctxt, BAD_CAST "<&", 2) < 0))
+                            (htmlParseLookupSequence(ctxt, '<', 0, 0, 0) < 0))
 			    goto done;
 			ctxt->checkIndex = 0;
 #ifdef DEBUG_PUSH
 			xmlGenericError(xmlGenericErrorContext,
 				"HPP: Parsing char data\n");
 #endif
-			htmlParseCharData(ctxt);
+                        while ((cur != '<') && (cur != 0)) {
+                            if (cur == '&') {
+			        htmlParseReference(ctxt);
+                            } else {
+			        htmlParseCharData(ctxt);
+                            }
+                            cur = in->cur[0];
+                        }
 		    }
 		}
-		if (cons == ctxt->nbChars) {
-		    if (ctxt->node != NULL) {
-			htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
-			             "detected an error in element content\n",
-				     NULL, NULL);
-		    }
-		    NEXT;
-		    break;
-		}
 
 		break;
 	    }
@@ -5942,7 +5849,7 @@
 		if (avail < 2)
 		    goto done;
 		if ((!terminate) &&
-		    (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+		    (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
 		    goto done;
 		htmlParseEndTag(ctxt);
 		if (ctxt->nameNr == 0) {
@@ -6124,12 +6031,12 @@
 	int res;
 
 	res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
+        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
 	if (res < 0) {
 	    ctxt->errNo = XML_PARSER_EOF;
 	    ctxt->disableSAX = 1;
 	    return (XML_PARSER_EOF);
 	}
-        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
 #ifdef DEBUG_PUSH
 	xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size);
 #endif
@@ -6148,12 +6055,12 @@
 		size_t current = ctxt->input->cur - ctxt->input->base;
 
 		nbchars = xmlCharEncInput(in, terminate);
+		xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
 		if (nbchars < 0) {
 		    htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
 			         "encoder error\n", NULL, NULL);
 		    return(XML_ERR_INVALID_ENCODING);
 		}
-		xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
 	    }
 	}
     }
@@ -6671,7 +6578,6 @@
     ctxt->vctxt.error = xmlParserValidityError;
     ctxt->vctxt.warning = xmlParserValidityWarning;
     ctxt->record_info = 0;
-    ctxt->nbChars = 0;
     ctxt->checkIndex = 0;
     ctxt->inSubset = 0;
     ctxt->errNo = XML_ERR_OK;
diff --git a/third_party/libxml/src/HTMLtree.c b/third_party/libxml/src/HTMLtree.c
index fe5d086f..8d0c779 100644
--- a/third_party/libxml/src/HTMLtree.c
+++ b/third_party/libxml/src/HTMLtree.c
@@ -706,49 +706,22 @@
 		 (!xmlStrcasecmp(cur->name, BAD_CAST "src")) ||
 		 ((!xmlStrcasecmp(cur->name, BAD_CAST "name")) &&
 		  (!xmlStrcasecmp(cur->parent->name, BAD_CAST "a"))))) {
+		xmlChar *escaped;
 		xmlChar *tmp = value;
-		/* xmlURIEscapeStr() escapes '"' so it can be safely used. */
-		xmlBufCCat(buf->buffer, "\"");
 
 		while (IS_BLANK_CH(*tmp)) tmp++;
 
-		/* URI Escape everything, except server side includes. */
-		for ( ; ; ) {
-		    xmlChar *escaped;
-		    xmlChar endChar;
-		    xmlChar *end = NULL;
-		    xmlChar *start = (xmlChar *)xmlStrstr(tmp, BAD_CAST "<!--");
-		    if (start != NULL) {
-			end = (xmlChar *)xmlStrstr(tmp, BAD_CAST "-->");
-			if (end != NULL) {
-			    *start = '\0';
-			}
-		    }
-
-		    /* Escape the whole string, or until start (set to '\0'). */
-		    escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+");
-		    if (escaped != NULL) {
-		        xmlBufCat(buf->buffer, escaped);
-		        xmlFree(escaped);
-		    } else {
-		        xmlBufCat(buf->buffer, tmp);
-		    }
-
-		    if (end == NULL) { /* Everything has been written. */
-			break;
-		    }
-
-		    /* Do not escape anything within server side includes. */
-		    *start = '<'; /* Restore the first character of "<!--". */
-		    end += 3; /* strlen("-->") */
-		    endChar = *end;
-		    *end = '\0';
-		    xmlBufCat(buf->buffer, start);
-		    *end = endChar;
-		    tmp = end;
+		/*
+		 * the < and > have already been escaped at the entity level
+		 * And doing so here breaks server side includes
+		 */
+		escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+<>");
+		if (escaped != NULL) {
+		    xmlBufWriteQuotedString(buf->buffer, escaped);
+		    xmlFree(escaped);
+		} else {
+		    xmlBufWriteQuotedString(buf->buffer, value);
 		}
-
-		xmlBufCCat(buf->buffer, "\"");
 	    } else {
 		xmlBufWriteQuotedString(buf->buffer, value);
 	    }
@@ -760,50 +733,6 @@
 }
 
 /**
- * htmlAttrListDumpOutput:
- * @buf:  the HTML buffer output
- * @doc:  the document
- * @cur:  the first attribute pointer
- * @encoding:  the encoding string
- *
- * Dump a list of HTML attributes
- */
-static void
-htmlAttrListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur, const char *encoding) {
-    if (cur == NULL) {
-	return;
-    }
-    while (cur != NULL) {
-        htmlAttrDumpOutput(buf, doc, cur, encoding);
-	cur = cur->next;
-    }
-}
-
-
-
-/**
- * htmlNodeListDumpOutput:
- * @buf:  the HTML buffer output
- * @doc:  the document
- * @cur:  the first node
- * @encoding:  the encoding string
- * @format:  should formatting spaces been added
- *
- * Dump an HTML node list, recursive behaviour,children are printed too.
- */
-static void
-htmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
-	               xmlNodePtr cur, const char *encoding, int format) {
-    if (cur == NULL) {
-	return;
-    }
-    while (cur != NULL) {
-        htmlNodeDumpFormatOutput(buf, doc, cur, encoding, format);
-	cur = cur->next;
-    }
-}
-
-/**
  * htmlNodeDumpFormatOutput:
  * @buf:  the HTML buffer output
  * @doc:  the document
@@ -816,6 +745,8 @@
 void
 htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
 	                 xmlNodePtr cur, const char *encoding, int format) {
+    xmlNodePtr root;
+    xmlAttrPtr attr;
     const htmlElemDesc * info;
 
     xmlInitParser();
@@ -823,172 +754,199 @@
     if ((cur == NULL) || (buf == NULL)) {
 	return;
     }
-    /*
-     * Special cases.
-     */
-    if (cur->type == XML_DTD_NODE)
-	return;
-    if ((cur->type == XML_HTML_DOCUMENT_NODE) ||
-        (cur->type == XML_DOCUMENT_NODE)){
-	htmlDocContentDumpOutput(buf, (xmlDocPtr) cur, encoding);
-	return;
-    }
-    if (cur->type == XML_ATTRIBUTE_NODE) {
-        htmlAttrDumpOutput(buf, doc, (xmlAttrPtr) cur, encoding);
-	return;
-    }
-    if (cur->type == HTML_TEXT_NODE) {
-	if (cur->content != NULL) {
-	    if (((cur->name == (const xmlChar *)xmlStringText) ||
-		 (cur->name != (const xmlChar *)xmlStringTextNoenc)) &&
-		((cur->parent == NULL) ||
-		 ((xmlStrcasecmp(cur->parent->name, BAD_CAST "script")) &&
-		  (xmlStrcasecmp(cur->parent->name, BAD_CAST "style"))))) {
-		xmlChar *buffer;
 
-		buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
-		if (buffer != NULL) {
-		    xmlOutputBufferWriteString(buf, (const char *)buffer);
-		    xmlFree(buffer);
-		}
-	    } else {
-		xmlOutputBufferWriteString(buf, (const char *)cur->content);
-	    }
-	}
-	return;
-    }
-    if (cur->type == HTML_COMMENT_NODE) {
-	if (cur->content != NULL) {
-	    xmlOutputBufferWriteString(buf, "<!--");
-	    xmlOutputBufferWriteString(buf, (const char *)cur->content);
-	    xmlOutputBufferWriteString(buf, "-->");
-	}
-	return;
-    }
-    if (cur->type == HTML_PI_NODE) {
-	if (cur->name == NULL)
-	    return;
-	xmlOutputBufferWriteString(buf, "<?");
-	xmlOutputBufferWriteString(buf, (const char *)cur->name);
-	if (cur->content != NULL) {
-	    xmlOutputBufferWriteString(buf, " ");
-	    xmlOutputBufferWriteString(buf, (const char *)cur->content);
-	}
-	xmlOutputBufferWriteString(buf, ">");
-	return;
-    }
-    if (cur->type == HTML_ENTITY_REF_NODE) {
-        xmlOutputBufferWriteString(buf, "&");
-	xmlOutputBufferWriteString(buf, (const char *)cur->name);
-        xmlOutputBufferWriteString(buf, ";");
-	return;
-    }
-    if (cur->type == HTML_PRESERVE_NODE) {
-	if (cur->content != NULL) {
-	    xmlOutputBufferWriteString(buf, (const char *)cur->content);
-	}
-	return;
-    }
+    root = cur;
+    while (1) {
+        switch (cur->type) {
+        case XML_HTML_DOCUMENT_NODE:
+        case XML_DOCUMENT_NODE:
+            if (((xmlDocPtr) cur)->intSubset != NULL) {
+                htmlDtdDumpOutput(buf, (xmlDocPtr) cur, NULL);
+            }
+            if (cur->children != NULL) {
+                cur = cur->children;
+                continue;
+            }
+            break;
 
-    /*
-     * Get specific HTML info for that node.
-     */
-    if (cur->ns == NULL)
-	info = htmlTagLookup(cur->name);
-    else
-	info = NULL;
+        case XML_ELEMENT_NODE:
+            /*
+             * Get specific HTML info for that node.
+             */
+            if (cur->ns == NULL)
+                info = htmlTagLookup(cur->name);
+            else
+                info = NULL;
 
-    xmlOutputBufferWriteString(buf, "<");
-    if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
-        xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
-	xmlOutputBufferWriteString(buf, ":");
-    }
-    xmlOutputBufferWriteString(buf, (const char *)cur->name);
-    if (cur->nsDef)
-	xmlNsListDumpOutput(buf, cur->nsDef);
-    if (cur->properties != NULL)
-        htmlAttrListDumpOutput(buf, doc, cur->properties, encoding);
-
-    if ((info != NULL) && (info->empty)) {
-        xmlOutputBufferWriteString(buf, ">");
-	if ((format) && (!info->isinline) && (cur->next != NULL)) {
-	    if ((cur->next->type != HTML_TEXT_NODE) &&
-		(cur->next->type != HTML_ENTITY_REF_NODE) &&
-		(cur->parent != NULL) &&
-		(cur->parent->name != NULL) &&
-		(cur->parent->name[0] != 'p')) /* p, pre, param */
-		xmlOutputBufferWriteString(buf, "\n");
-	}
-	return;
-    }
-    if (((cur->type == XML_ELEMENT_NODE) || (cur->content == NULL)) &&
-	(cur->children == NULL)) {
-        if ((info != NULL) && (info->saveEndTag != 0) &&
-	    (xmlStrcmp(BAD_CAST info->name, BAD_CAST "html")) &&
-	    (xmlStrcmp(BAD_CAST info->name, BAD_CAST "body"))) {
-	    xmlOutputBufferWriteString(buf, ">");
-	} else {
-	    xmlOutputBufferWriteString(buf, "></");
+            xmlOutputBufferWriteString(buf, "<");
             if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
                 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
                 xmlOutputBufferWriteString(buf, ":");
             }
-	    xmlOutputBufferWriteString(buf, (const char *)cur->name);
-	    xmlOutputBufferWriteString(buf, ">");
-	}
-	if ((format) && (cur->next != NULL) &&
-            (info != NULL) && (!info->isinline)) {
-	    if ((cur->next->type != HTML_TEXT_NODE) &&
-		(cur->next->type != HTML_ENTITY_REF_NODE) &&
-		(cur->parent != NULL) &&
-		(cur->parent->name != NULL) &&
-		(cur->parent->name[0] != 'p')) /* p, pre, param */
-		xmlOutputBufferWriteString(buf, "\n");
-	}
-	return;
-    }
-    xmlOutputBufferWriteString(buf, ">");
-    if ((cur->type != XML_ELEMENT_NODE) &&
-	(cur->content != NULL)) {
-	    /*
-	     * Uses the OutputBuffer property to automatically convert
-	     * invalids to charrefs
-	     */
+            xmlOutputBufferWriteString(buf, (const char *)cur->name);
+            if (cur->nsDef)
+                xmlNsListDumpOutput(buf, cur->nsDef);
+            attr = cur->properties;
+            while (attr != NULL) {
+                htmlAttrDumpOutput(buf, doc, attr, encoding);
+                attr = attr->next;
+            }
 
-            xmlOutputBufferWriteString(buf, (const char *) cur->content);
-    }
-    if (cur->children != NULL) {
-        if ((format) && (info != NULL) && (!info->isinline) &&
-	    (cur->children->type != HTML_TEXT_NODE) &&
-	    (cur->children->type != HTML_ENTITY_REF_NODE) &&
-	    (cur->children != cur->last) &&
-	    (cur->name != NULL) &&
-	    (cur->name[0] != 'p')) /* p, pre, param */
-	    xmlOutputBufferWriteString(buf, "\n");
-	htmlNodeListDumpOutput(buf, doc, cur->children, encoding, format);
-        if ((format) && (info != NULL) && (!info->isinline) &&
-	    (cur->last->type != HTML_TEXT_NODE) &&
-	    (cur->last->type != HTML_ENTITY_REF_NODE) &&
-	    (cur->children != cur->last) &&
-	    (cur->name != NULL) &&
-	    (cur->name[0] != 'p')) /* p, pre, param */
-	    xmlOutputBufferWriteString(buf, "\n");
-    }
-    xmlOutputBufferWriteString(buf, "</");
-    if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
-        xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
-	xmlOutputBufferWriteString(buf, ":");
-    }
-    xmlOutputBufferWriteString(buf, (const char *)cur->name);
-    xmlOutputBufferWriteString(buf, ">");
-    if ((format) && (info != NULL) && (!info->isinline) &&
-	(cur->next != NULL)) {
-        if ((cur->next->type != HTML_TEXT_NODE) &&
-	    (cur->next->type != HTML_ENTITY_REF_NODE) &&
-	    (cur->parent != NULL) &&
-	    (cur->parent->name != NULL) &&
-	    (cur->parent->name[0] != 'p')) /* p, pre, param */
-	    xmlOutputBufferWriteString(buf, "\n");
+            if ((info != NULL) && (info->empty)) {
+                xmlOutputBufferWriteString(buf, ">");
+            } else if (cur->children == NULL) {
+                if ((info != NULL) && (info->saveEndTag != 0) &&
+                    (xmlStrcmp(BAD_CAST info->name, BAD_CAST "html")) &&
+                    (xmlStrcmp(BAD_CAST info->name, BAD_CAST "body"))) {
+                    xmlOutputBufferWriteString(buf, ">");
+                } else {
+                    xmlOutputBufferWriteString(buf, "></");
+                    if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+                        xmlOutputBufferWriteString(buf,
+                                (const char *)cur->ns->prefix);
+                        xmlOutputBufferWriteString(buf, ":");
+                    }
+                    xmlOutputBufferWriteString(buf, (const char *)cur->name);
+                    xmlOutputBufferWriteString(buf, ">");
+                }
+            } else {
+                xmlOutputBufferWriteString(buf, ">");
+                if ((format) && (info != NULL) && (!info->isinline) &&
+                    (cur->children->type != HTML_TEXT_NODE) &&
+                    (cur->children->type != HTML_ENTITY_REF_NODE) &&
+                    (cur->children != cur->last) &&
+                    (cur->name != NULL) &&
+                    (cur->name[0] != 'p')) /* p, pre, param */
+                    xmlOutputBufferWriteString(buf, "\n");
+                cur = cur->children;
+                continue;
+            }
+
+            if ((format) && (cur->next != NULL) &&
+                (info != NULL) && (!info->isinline)) {
+                if ((cur->next->type != HTML_TEXT_NODE) &&
+                    (cur->next->type != HTML_ENTITY_REF_NODE) &&
+                    (cur->parent != NULL) &&
+                    (cur->parent->name != NULL) &&
+                    (cur->parent->name[0] != 'p')) /* p, pre, param */
+                    xmlOutputBufferWriteString(buf, "\n");
+            }
+
+            break;
+
+        case XML_ATTRIBUTE_NODE:
+            htmlAttrDumpOutput(buf, doc, (xmlAttrPtr) cur, encoding);
+            break;
+
+        case HTML_TEXT_NODE:
+            if (cur->content == NULL)
+                break;
+            if (((cur->name == (const xmlChar *)xmlStringText) ||
+                 (cur->name != (const xmlChar *)xmlStringTextNoenc)) &&
+                ((cur->parent == NULL) ||
+                 ((xmlStrcasecmp(cur->parent->name, BAD_CAST "script")) &&
+                  (xmlStrcasecmp(cur->parent->name, BAD_CAST "style"))))) {
+                xmlChar *buffer;
+
+                buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
+                if (buffer != NULL) {
+                    xmlOutputBufferWriteString(buf, (const char *)buffer);
+                    xmlFree(buffer);
+                }
+            } else {
+                xmlOutputBufferWriteString(buf, (const char *)cur->content);
+            }
+            break;
+
+        case HTML_COMMENT_NODE:
+            if (cur->content != NULL) {
+                xmlOutputBufferWriteString(buf, "<!--");
+                xmlOutputBufferWriteString(buf, (const char *)cur->content);
+                xmlOutputBufferWriteString(buf, "-->");
+            }
+            break;
+
+        case HTML_PI_NODE:
+            if (cur->name != NULL) {
+                xmlOutputBufferWriteString(buf, "<?");
+                xmlOutputBufferWriteString(buf, (const char *)cur->name);
+                if (cur->content != NULL) {
+                    xmlOutputBufferWriteString(buf, " ");
+                    xmlOutputBufferWriteString(buf,
+                            (const char *)cur->content);
+                }
+                xmlOutputBufferWriteString(buf, ">");
+            }
+            break;
+
+        case HTML_ENTITY_REF_NODE:
+            xmlOutputBufferWriteString(buf, "&");
+            xmlOutputBufferWriteString(buf, (const char *)cur->name);
+            xmlOutputBufferWriteString(buf, ";");
+            break;
+
+        case HTML_PRESERVE_NODE:
+            if (cur->content != NULL) {
+                xmlOutputBufferWriteString(buf, (const char *)cur->content);
+            }
+            break;
+
+        default:
+            break;
+        }
+
+        while (1) {
+            if (cur == root)
+                return;
+            if (cur->next != NULL) {
+                cur = cur->next;
+                break;
+            }
+
+            /*
+             * The parent should never be NULL here but we want to handle
+             * corrupted documents gracefully.
+             */
+            if (cur->parent == NULL)
+                return;
+            cur = cur->parent;
+
+            if ((cur->type == XML_HTML_DOCUMENT_NODE) ||
+                (cur->type == XML_DOCUMENT_NODE)) {
+                xmlOutputBufferWriteString(buf, "\n");
+            } else {
+                if ((format) && (cur->ns == NULL))
+                    info = htmlTagLookup(cur->name);
+                else
+                    info = NULL;
+
+                if ((format) && (info != NULL) && (!info->isinline) &&
+                    (cur->last->type != HTML_TEXT_NODE) &&
+                    (cur->last->type != HTML_ENTITY_REF_NODE) &&
+                    (cur->children != cur->last) &&
+                    (cur->name != NULL) &&
+                    (cur->name[0] != 'p')) /* p, pre, param */
+                    xmlOutputBufferWriteString(buf, "\n");
+
+                xmlOutputBufferWriteString(buf, "</");
+                if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+                    xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
+                    xmlOutputBufferWriteString(buf, ":");
+                }
+                xmlOutputBufferWriteString(buf, (const char *)cur->name);
+                xmlOutputBufferWriteString(buf, ">");
+
+                if ((format) && (info != NULL) && (!info->isinline) &&
+                    (cur->next != NULL)) {
+                    if ((cur->next->type != HTML_TEXT_NODE) &&
+                        (cur->next->type != HTML_ENTITY_REF_NODE) &&
+                        (cur->parent != NULL) &&
+                        (cur->parent->name != NULL) &&
+                        (cur->parent->name[0] != 'p')) /* p, pre, param */
+                        xmlOutputBufferWriteString(buf, "\n");
+                }
+            }
+        }
     }
 }
 
@@ -1020,26 +978,7 @@
 void
 htmlDocContentDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
 	                       const char *encoding, int format) {
-    int type;
-
-    xmlInitParser();
-
-    if ((buf == NULL) || (cur == NULL))
-        return;
-
-    /*
-     * force to output the stuff as HTML, especially for entities
-     */
-    type = cur->type;
-    cur->type = XML_HTML_DOCUMENT_NODE;
-    if (cur->intSubset != NULL) {
-        htmlDtdDumpOutput(buf, cur, NULL);
-    }
-    if (cur->children != NULL) {
-        htmlNodeListDumpOutput(buf, cur, cur->children, encoding, format);
-    }
-    xmlOutputBufferWriteString(buf, "\n");
-    cur->type = (xmlElementType) type;
+    htmlNodeDumpFormatOutput(buf, cur, (xmlNodePtr) cur, encoding, format);
 }
 
 /**
@@ -1053,7 +992,7 @@
 void
 htmlDocContentDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
 	                 const char *encoding) {
-    htmlDocContentDumpFormatOutput(buf, cur, encoding, 1);
+    htmlNodeDumpFormatOutput(buf, cur, (xmlNodePtr) cur, encoding, 1);
 }
 
 /************************************************************************
diff --git a/third_party/libxml/src/Makefile.am b/third_party/libxml/src/Makefile.am
index be1a883..4ef0eb92 100644
--- a/third_party/libxml/src/Makefile.am
+++ b/third_party/libxml/src/Makefile.am
@@ -2,9 +2,9 @@
 
 ACLOCAL_AMFLAGS = -I m4
 
-SUBDIRS = include . doc example xstc $(PYTHON_SUBDIR)
+SUBDIRS = include . doc example fuzz xstc $(PYTHON_SUBDIR)
 
-DIST_SUBDIRS = include . doc example python xstc
+DIST_SUBDIRS = include . doc example python xstc fuzz
 
 AM_CPPFLAGS = -I$(top_builddir)/include -I$(srcdir)/include
 
@@ -210,6 +210,7 @@
 	    $(CHECKER) ./runxmlconf$(EXEEXT)
 	@(if [ "$(PYTHON_SUBDIR)" != "" ] ; then cd python ; \
 	    $(MAKE) tests ; fi)
+	@cd fuzz; $(MAKE) tests
 
 check: all runtests
 
@@ -906,14 +907,16 @@
 	  if [ ! -d $$i ] ; then \
 	  if [ ! -f $(srcdir)/result/regexp/$$name ] ; then \
 	      echo New test file $$name ; \
-	      $(CHECKER) $(top_builddir)/testRegexp -i $$i > $(srcdir)/result/regexp/$$name; \
+	      $(CHECKER) $(top_builddir)/testRegexp -i $$i > $(srcdir)/result/regexp/$$name 2> $(srcdir)/result/regexp/$$name.err ; \
+	      if [ ! -s "$(srcdir)/result/regexp/$$name.err" ] ; then rm $(srcdir)/result/regexp/$$name.err; fi ; \
 	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	  else \
-	      log=`$(CHECKER) $(top_builddir)/testRegexp -i $$i 2>&1 > result.$$name ; \
+	      log=`$(CHECKER) $(top_builddir)/testRegexp -i $$i > result.$$name 2> error.$$name ; \
 	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
-	      diff $(srcdir)/result/regexp/$$name result.$$name` ; \
-	      if [ -n "$$log" ] ; then echo $$name result ; echo "$$log" ; fi ; \
-	      rm result.$$name ; \
+	      diff $(srcdir)/result/regexp/$$name result.$$name ; \
+	      if [ -s "$(srcdir)/result/regexp/$$name.err" -o -s "error.$$name" ] ; then diff $(srcdir)/result/regexp/$$name.err error.$$name ; fi` ; \
+	      if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \
+	      rm result.$$name error.$$name ; \
 	  fi ; fi ; done)
 
 # Disabled for now
diff --git a/third_party/libxml/src/SAX2.c b/third_party/libxml/src/SAX2.c
index 9df0184..4450a3f 100644
--- a/third_party/libxml/src/SAX2.c
+++ b/third_party/libxml/src/SAX2.c
@@ -1663,23 +1663,23 @@
 	}
     }
 
-    /*
-     * Insert all the defaulted attributes from the DTD especially namespaces
-     */
-    if ((!ctxt->html) &&
-	((ctxt->myDoc->intSubset != NULL) ||
-	 (ctxt->myDoc->extSubset != NULL))) {
-	xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
-    }
+    if (!ctxt->html) {
+        /*
+         * Insert all the defaulted attributes from the DTD especially
+         * namespaces
+         */
+        if ((ctxt->myDoc->intSubset != NULL) ||
+            (ctxt->myDoc->extSubset != NULL)) {
+            xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
+        }
 
-    /*
-     * process all the attributes whose name start with "xmlns"
-     */
-    if (atts != NULL) {
-        i = 0;
-	att = atts[i++];
-	value = atts[i++];
-	if (!ctxt->html) {
+        /*
+         * process all the attributes whose name start with "xmlns"
+         */
+        if (atts != NULL) {
+            i = 0;
+            att = atts[i++];
+            value = atts[i++];
 	    while ((att != NULL) && (value != NULL)) {
 		if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
 		    (att[3] == 'n') && (att[4] == 's'))
@@ -1688,30 +1688,30 @@
 		att = atts[i++];
 		value = atts[i++];
 	    }
-	}
-    }
+        }
 
-    /*
-     * Search the namespace, note that since the attributes have been
-     * processed, the local namespaces are available.
-     */
-    ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
-    if ((ns == NULL) && (parent != NULL))
-	ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
-    if ((prefix != NULL) && (ns == NULL)) {
-	ns = xmlNewNs(ret, NULL, prefix);
-	xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
-		     "Namespace prefix %s is not defined\n",
-		     prefix, NULL);
-    }
+        /*
+         * Search the namespace, note that since the attributes have been
+         * processed, the local namespaces are available.
+         */
+        ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
+        if ((ns == NULL) && (parent != NULL))
+            ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
+        if ((prefix != NULL) && (ns == NULL)) {
+            ns = xmlNewNs(ret, NULL, prefix);
+            xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
+                         "Namespace prefix %s is not defined\n",
+                         prefix, NULL);
+        }
 
-    /*
-     * set the namespace node, making sure that if the default namespace
-     * is unbound on a parent we simply keep it NULL
-     */
-    if ((ns != NULL) && (ns->href != NULL) &&
-	((ns->href[0] != 0) || (ns->prefix != NULL)))
-	xmlSetNs(ret, ns);
+        /*
+         * set the namespace node, making sure that if the default namespace
+         * is unbound on a parent we simply keep it NULL
+         */
+        if ((ns != NULL) && (ns->href != NULL) &&
+            ((ns->href[0] != 0) || (ns->prefix != NULL)))
+            xmlSetNs(ret, ns);
+    }
 
     /*
      * process all the other attributes
diff --git a/third_party/libxml/src/buf.c b/third_party/libxml/src/buf.c
index 8ad18a1..24368d37 100644
--- a/third_party/libxml/src/buf.c
+++ b/third_party/libxml/src/buf.c
@@ -1334,8 +1334,12 @@
 int
 xmlBufSetInputBaseCur(xmlBufPtr buf, xmlParserInputPtr input,
                       size_t base, size_t cur) {
-    if ((input == NULL) || (buf == NULL) || (buf->error))
+    if (input == NULL)
         return(-1);
+    if ((buf == NULL) || (buf->error)) {
+        input->base = input->cur = input->end = BAD_CAST "";
+        return(-1);
+    }
     CHECK_COMPAT(buf)
     input->base = &buf->content[base];
     input->cur = input->base + cur;
diff --git a/third_party/libxml/src/config.h.in b/third_party/libxml/src/config.h.in
index a751769c..5f87036 100644
--- a/third_party/libxml/src/config.h.in
+++ b/third_party/libxml/src/config.h.in
@@ -1,5 +1,8 @@
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* A form that will not confuse apibuild.py */
+#undef ATTRIBUTE_DESTRUCTOR
+
 /* Type cast for the gethostbyname() argument */
 #undef GETHOSTBYNAME_ARG_CAST
 
@@ -9,6 +12,9 @@
 /* Define to 1 if you have the <arpa/nameser.h> header file. */
 #undef HAVE_ARPA_NAMESER_H
 
+/* Define if __attribute__((destructor)) is accepted */
+#undef HAVE_ATTRIBUTE_DESTRUCTOR
+
 /* Whether struct sockaddr::__ss_family exists */
 #undef HAVE_BROKEN_SS_FAMILY
 
diff --git a/third_party/libxml/src/configure.ac b/third_party/libxml/src/configure.ac
index 09418af..a4c675b 100644
--- a/third_party/libxml/src/configure.ac
+++ b/third_party/libxml/src/configure.ac
@@ -1,15 +1,20 @@
 dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ([2.63])
-AC_INIT
+
+m4_define([MAJOR_VERSION], 2)
+m4_define([MINOR_VERSION], 9)
+m4_define([MICRO_VERSION], 10)
+
+AC_INIT([libxml2],[MAJOR_VERSION.MINOR_VERSION.MICRO_VERSION])
 AC_CONFIG_SRCDIR([entities.c])
 AC_CONFIG_HEADERS([config.h])
 AM_MAINTAINER_MODE([enable])
 AC_CONFIG_MACRO_DIR([m4])
 AC_CANONICAL_HOST
 
-LIBXML_MAJOR_VERSION=2
-LIBXML_MINOR_VERSION=9
-LIBXML_MICRO_VERSION=10
+LIBXML_MAJOR_VERSION=MAJOR_VERSION
+LIBXML_MINOR_VERSION=MINOR_VERSION
+LIBXML_MICRO_VERSION=MICRO_VERSION
 LIBXML_MICRO_VERSION_SUFFIX=
 LIBXML_VERSION=$LIBXML_MAJOR_VERSION.$LIBXML_MINOR_VERSION.$LIBXML_MICRO_VERSION$LIBXML_MICRO_VERSION_SUFFIX
 LIBXML_VERSION_INFO=`expr $LIBXML_MAJOR_VERSION + $LIBXML_MINOR_VERSION`:$LIBXML_MICRO_VERSION:$LIBXML_MINOR_VERSION
@@ -50,7 +55,7 @@
 
 VERSION=${LIBXML_VERSION}
 
-AM_INIT_AUTOMAKE(libxml2, $VERSION)
+AM_INIT_AUTOMAKE([foreign])
 
 # Support silent build rules, requires at least automake-1.11. Disable
 # by either passing --disable-silent-rules to configure or passing V=1
@@ -641,6 +646,17 @@
       [Type cast for the send() function 2nd arg])
 fi
 
+dnl Checking whether __attribute__((destructor)) is accepted by the compiler
+AC_MSG_CHECKING([whether __attribute__((destructor)) is accepted])
+AC_TRY_COMPILE2([
+void __attribute__((destructor))
+f(void) {}], [], [
+  AC_MSG_RESULT(yes)
+  AC_DEFINE([HAVE_ATTRIBUTE_DESTRUCTOR], [1],[Define if __attribute__((destructor)) is accepted])
+  AC_DEFINE([ATTRIBUTE_DESTRUCTOR], [__attribute__((destructor))],[A form that will not confuse apibuild.py])],[
+  AC_MSG_RESULT(no)])
+
+
 dnl ***********************Checking for availability of IPv6*******************
 
 AC_MSG_CHECKING([whether to enable IPv6])
@@ -1503,8 +1519,8 @@
 
             AC_CHECK_HEADER(unicode/ucnv.h,
             AC_MSG_CHECKING(for icu)
-            AC_TRY_LINK([#include <unicode/ucnv.h>],[
-        UConverter *utf = ucnv_open("UTF-8", NULL);],[
+            AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <unicode/ucnv.h>]], [[
+        UConverter *utf = ucnv_open("UTF-8", NULL);]])],[
                 AC_MSG_RESULT(yes)
                 have_libicu=yes],[
                 AC_MSG_RESULT(no)
@@ -1515,8 +1531,8 @@
                 LDFLAGS="${LDFLAGS} ${ICU_LIBS}"
                 LIBS="${LIBS} -licucore"
 
-                AC_TRY_LINK([#include <unicode/ucnv.h>],[
-        UConverter *utf = ucnv_open("UTF-8", NULL);],[
+                AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <unicode/ucnv.h>]], [[
+        UConverter *utf = ucnv_open("UTF-8", NULL);]])],[
                     AC_MSG_RESULT(yes)
                     have_libicu=yes
                     ICU_LIBS="${ICU_LIBS} -licucore"
@@ -1704,7 +1720,7 @@
 ln -s $srcdir/Copyright COPYING
 
 # keep on one line for cygwin c.f. #130896
-AC_CONFIG_FILES([libxml2.spec:libxml.spec.in Makefile include/Makefile include/libxml/Makefile doc/Makefile doc/examples/Makefile doc/devhelp/Makefile example/Makefile python/Makefile python/tests/Makefile xstc/Makefile include/libxml/xmlversion.h libxml-2.0.pc libxml-2.0-uninstalled.pc libxml2-config.cmake])
+AC_CONFIG_FILES([libxml2.spec:libxml.spec.in Makefile include/Makefile include/libxml/Makefile doc/Makefile doc/examples/Makefile doc/devhelp/Makefile example/Makefile fuzz/Makefile python/Makefile python/tests/Makefile xstc/Makefile include/libxml/xmlversion.h libxml-2.0.pc libxml-2.0-uninstalled.pc libxml2-config.cmake])
 AC_CONFIG_FILES([python/setup.py], [chmod +x python/setup.py])
 AC_CONFIG_FILES([xml2-config], [chmod +x xml2-config])
 AC_OUTPUT
diff --git a/third_party/libxml/src/encoding.c b/third_party/libxml/src/encoding.c
index 65c5889..c34aca4 100644
--- a/third_party/libxml/src/encoding.c
+++ b/third_party/libxml/src/encoding.c
@@ -170,7 +170,7 @@
  * Returns 0 if success, or -1 otherwise
  * The value of @inlen after return is the number of octets consumed
  *     if the return value is positive, else unpredictable.
- * The value of @outlen after return is the number of octets consumed.
+ * The value of @outlen after return is the number of octets produced.
  */
 static int
 asciiToUTF8(unsigned char* out, int *outlen,
@@ -217,7 +217,7 @@
  * Returns 0 if success, -2 if the transcoding fails, or -1 otherwise
  * The value of @inlen after return is the number of octets consumed
  *     if the return value is positive, else unpredictable.
- * The value of @outlen after return is the number of octets consumed.
+ * The value of @outlen after return is the number of octets produced.
  */
 static int
 UTF8Toascii(unsigned char* out, int *outlen,
@@ -301,7 +301,7 @@
  * Returns the number of bytes written if success, or -1 otherwise
  * The value of @inlen after return is the number of octets consumed
  *     if the return value is positive, else unpredictable.
- * The value of @outlen after return is the number of octets consumed.
+ * The value of @outlen after return is the number of octets produced.
  */
 int
 isolat1ToUTF8(unsigned char* out, int *outlen,
@@ -396,7 +396,7 @@
            or -1 otherwise
  * The value of @inlen after return is the number of octets consumed
  *     if the return value is positive, else unpredictable.
- * The value of @outlen after return is the number of octets consumed.
+ * The value of @outlen after return is the number of octets produced.
  */
 int
 UTF8Toisolat1(unsigned char* out, int *outlen,
@@ -496,13 +496,18 @@
 {
     unsigned char* outstart = out;
     const unsigned char* processed = inb;
-    unsigned char* outend = out + *outlen;
+    unsigned char* outend;
     unsigned short* in = (unsigned short*) inb;
     unsigned short* inend;
     unsigned int c, d, inlen;
     unsigned char *tmp;
     int bits;
 
+    if (*outlen == 0) {
+        *inlenb = 0;
+        return(0);
+    }
+    outend = out + *outlen;
     if ((*inlenb % 2) == 1)
         (*inlenb)--;
     inlen = *inlenb / 2;
@@ -1784,7 +1789,7 @@
  * @cd:		iconv converter data structure
  * @out:  a pointer to an array of bytes to store the result
  * @outlen:  the length of @out
- * @in:  a pointer to an array of ISO Latin 1 chars
+ * @in:  a pointer to an array of input bytes
  * @inlen:  the length of @in
  *
  * Returns 0 if success, or
@@ -1795,7 +1800,7 @@
  *
  * The value of @inlen after return is the number of octets consumed
  *     as the return value is positive, else unpredictable.
- * The value of @outlen after return is the number of octets consumed.
+ * The value of @outlen after return is the number of octets produced.
  */
 static int
 xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen,
@@ -1851,7 +1856,7 @@
  * @toUnicode : non-zero if toUnicode. 0 otherwise.
  * @out:  a pointer to an array of bytes to store the result
  * @outlen:  the length of @out
- * @in:  a pointer to an array of ISO Latin 1 chars
+ * @in:  a pointer to an array of input bytes
  * @inlen:  the length of @in
  * @flush: if true, indicates end of input
  *
@@ -1863,7 +1868,7 @@
  *
  * The value of @inlen after return is the number of octets consumed
  *     as the return value is positive, else unpredictable.
- * The value of @outlen after return is the number of octets consumed.
+ * The value of @outlen after return is the number of octets produced.
  */
 static int
 xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen,
@@ -1912,6 +1917,25 @@
  *									*
  ************************************************************************/
 
+/**
+ * xmlEncInputChunk:
+ * @handler:  encoding handler
+ * @out:  a pointer to an array of bytes to store the result
+ * @outlen:  the length of @out
+ * @in:  a pointer to an array of input bytes
+ * @inlen:  the length of @in
+ * @flush:  flush (ICU-related)
+ *
+ * Returns 0 if success, or
+ *     -1 by lack of space, or
+ *     -2 if the transcoding fails (for *in is not valid utf8 string or
+ *        the result of transformation can't fit into the encoding we want), or
+ *     -3 if there the last byte can't form a single output char.
+ *
+ * The value of @inlen after return is the number of octets consumed
+ *     as the return value is 0, else unpredictable.
+ * The value of @outlen after return is the number of octets produced.
+ */
 static int
 xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
                  int *outlen, const unsigned char *in, int *inlen, int flush) {
@@ -1920,6 +1944,8 @@
 
     if (handler->input != NULL) {
         ret = handler->input(out, outlen, in, inlen);
+        if (ret > 0)
+           ret = 0;
     }
 #ifdef LIBXML_ICONV_ENABLED
     else if (handler->iconv_in != NULL) {
@@ -1941,7 +1967,25 @@
     return(ret);
 }
 
-/* Returns -4 if no output function was found. */
+/**
+ * xmlEncOutputChunk:
+ * @handler:  encoding handler
+ * @out:  a pointer to an array of bytes to store the result
+ * @outlen:  the length of @out
+ * @in:  a pointer to an array of input bytes
+ * @inlen:  the length of @in
+ *
+ * Returns 0 if success, or
+ *     -1 by lack of space, or
+ *     -2 if the transcoding fails (for *in is not valid utf8 string or
+ *        the result of transformation can't fit into the encoding we want), or
+ *     -3 if there the last byte can't form a single output char.
+ *     -4 if no output function was found.
+ *
+ * The value of @inlen after return is the number of octets consumed
+ *     as the return value is 0, else unpredictable.
+ * The value of @outlen after return is the number of octets produced.
+ */
 static int
 xmlEncOutputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
                   int *outlen, const unsigned char *in, int *inlen) {
@@ -1949,6 +1993,8 @@
 
     if (handler->output != NULL) {
         ret = handler->output(out, outlen, in, inlen);
+        if (ret > 0)
+           ret = 0;
     }
 #ifdef LIBXML_ICONV_ENABLED
     else if (handler->iconv_out != NULL) {
@@ -2054,7 +2100,7 @@
      */
     if (ret == -3) ret = 0;
     if (ret == -1) ret = 0;
-    return(ret);
+    return(written ? written : ret);
 }
 
 /**
@@ -2184,7 +2230,7 @@
      */
     if (ret == -3) ret = 0;
     if (ret == -1) ret = 0;
-    return(ret);
+    return(c_out ? c_out : ret);
 }
 
 /**
@@ -2394,7 +2440,7 @@
 {
     int ret;
     size_t written;
-    size_t writtentot = 0;
+    int writtentot = 0;
     size_t toconv;
     int c_in;
     int c_out;
@@ -2427,7 +2473,7 @@
 	xmlGenericError(xmlGenericErrorContext,
 		"initialized encoder\n");
 #endif
-        return(0);
+        return(c_out);
     }
 
     /*
@@ -2540,7 +2586,7 @@
             goto retry;
 	}
     }
-    return(ret);
+    return(writtentot ? writtentot : ret);
 }
 #endif
 
@@ -2705,7 +2751,7 @@
             goto retry;
 	}
     }
-    return(ret);
+    return(writtentot ? writtentot : ret);
 }
 
 /**
diff --git a/third_party/libxml/src/error.c b/third_party/libxml/src/error.c
index 3e41e17..9ff1c2ba 100644
--- a/third_party/libxml/src/error.c
+++ b/third_party/libxml/src/error.c
@@ -557,6 +557,7 @@
 	 * of the usual "base" (doc->URL) for the node (bug 152623).
 	 */
         xmlNodePtr prev = baseptr;
+        char *href = NULL;
 	int inclcount = 0;
 	while (prev != NULL) {
 	    if (prev->prev == NULL)
@@ -564,21 +565,20 @@
 	    else {
 	        prev = prev->prev;
 		if (prev->type == XML_XINCLUDE_START) {
-		    if (--inclcount < 0)
-		        break;
+		    if (inclcount > 0) {
+                        --inclcount;
+                    } else {
+                        href = (char *) xmlGetProp(prev, BAD_CAST "href");
+                        if (href != NULL)
+		            break;
+                    }
 		} else if (prev->type == XML_XINCLUDE_END)
 		    inclcount++;
 	    }
 	}
-	if (prev != NULL) {
-	    if (prev->type == XML_XINCLUDE_START) {
-		prev->type = XML_ELEMENT_NODE;
-		to->file = (char *) xmlGetProp(prev, BAD_CAST "href");
-		prev->type = XML_XINCLUDE_START;
-	    } else {
-		to->file = (char *) xmlGetProp(prev, BAD_CAST "href");
-	    }
-	} else
+        if (href != NULL)
+            to->file = href;
+	else
 #endif
 	    to->file = (char *) xmlStrdup(baseptr->doc->URL);
 	if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) {
diff --git a/third_party/libxml/src/fuzz/Makefile.am b/third_party/libxml/src/fuzz/Makefile.am
new file mode 100644
index 0000000..49b9554
--- /dev/null
+++ b/third_party/libxml/src/fuzz/Makefile.am
@@ -0,0 +1,138 @@
+AUTOMAKE_OPTIONS = -Wno-syntax
+EXTRA_PROGRAMS = genSeed html regexp schema uri xml xpath
+check_PROGRAMS = testFuzzer
+CLEANFILES = $(EXTRA_PROGRAMS)
+AM_CPPFLAGS = -I$(top_srcdir)/include
+DEPENDENCIES = $(top_builddir)/libxml2.la
+LDADD = $(STATIC_BINARIES) $(top_builddir)/libxml2.la $(THREAD_LIBS) $(Z_LIBS) $(LZMA_LIBS) $(ICONV_LIBS) $(M_LIBS) $(WIN32_EXTRA_LIBADD)
+
+XML_MAX_LEN = 80000
+# Single quotes to avoid wildcard expansion by the shell
+XML_SEED_CORPUS_SRC = \
+    '$(top_srcdir)/test/*' \
+    '$(top_srcdir)/test/errors/*.xml' \
+    '$(top_srcdir)/test/errors10/*.xml' \
+    '$(top_srcdir)/test/namespaces/*' \
+    '$(top_srcdir)/test/valid/*.xml' \
+    '$(top_srcdir)/test/VC/*' \
+    '$(top_srcdir)/test/VCM/*' \
+    '$(top_srcdir)/test/XInclude/docs/*' \
+    '$(top_srcdir)/test/xmlid/*'
+
+testFuzzer_SOURCES = testFuzzer.c fuzz.c
+
+.PHONY: tests corpus clean-corpus
+
+corpus: seed/html.stamp seed/schema.stamp seed/xml.stamp seed/xpath.stamp
+
+tests: testFuzzer$(EXEEXT) corpus
+	@echo "## Running fuzzer tests"
+	@./testFuzzer$(EXEEXT)
+
+clean-corpus:
+	rm -rf seed/html.stamp seed/html
+	rm -rf seed/schema.stamp seed/schema
+	rm -rf seed/xml.stamp seed/xml
+	rm -rf seed/xpath.stamp seed/xpath
+
+# Seed corpus
+
+genSeed_SOURCES = genSeed.c fuzz.c
+
+# XML fuzzer
+
+seed/xml.stamp: genSeed$(EXEEXT)
+	@mkdir -p seed/xml
+	@./genSeed$(EXEEXT) xml $(XML_SEED_CORPUS_SRC)
+	@touch seed/xml.stamp
+
+xml_SOURCES = xml.c fuzz.c
+xml_LDFLAGS = -fsanitize=fuzzer
+
+fuzz-xml: xml$(EXEEXT) seed/xml.stamp
+	@mkdir -p corpus/xml
+	./xml$(EXEEXT) \
+	    -dict=xml.dict \
+	    -max_len=$(XML_MAX_LEN) \
+	    -timeout=20 \
+	    corpus/xml seed/xml
+
+# HTML fuzzer
+
+seed/html.stamp: genSeed$(EXEEXT)
+	@mkdir -p seed/html
+	@./genSeed$(EXEEXT) html '$(top_srcdir)/test/HTML/*'
+	@touch seed/html.stamp
+
+html_SOURCES = html.c fuzz.c
+html_LDFLAGS = -fsanitize=fuzzer
+
+fuzz-html: html$(EXEEXT) seed/html.stamp
+	@mkdir -p corpus/html
+	./html$(EXEEXT) \
+	    -dict=html.dict \
+	    -max_len=1000000 \
+	    -timeout=20 \
+	    corpus/html seed/html
+
+# Regexp fuzzer
+
+regexp_SOURCES = regexp.c fuzz.c
+regexp_LDFLAGS = -fsanitize=fuzzer
+
+fuzz-regexp: regexp$(EXEEXT)
+	@mkdir -p corpus/regexp
+	./regexp$(EXEEXT) \
+	    -dict=regexp.dict \
+	    -max_len=200 \
+	    -timeout=5 \
+	    corpus/regexp $(srcdir)/seed/regexp
+
+# URI fuzzer
+
+uri_SOURCES = uri.c fuzz.c
+uri_LDFLAGS = -fsanitize=fuzzer
+
+fuzz-uri: uri$(EXEEXT)
+	@mkdir -p corpus/uri
+	./uri$(EXEEXT) \
+	    -max_len=10000 \
+	    -timeout=5 \
+	    corpus/uri $(srcdir)/seed/uri
+
+# XML Schema fuzzer
+
+seed/schema.stamp: genSeed$(EXEEXT)
+	@mkdir -p seed/schema
+	@./genSeed$(EXEEXT) schema '$(top_srcdir)/test/schemas/*.xsd'
+	@touch seed/schema.stamp
+
+schema_SOURCES = schema.c fuzz.c
+schema_LDFLAGS = -fsanitize=fuzzer
+
+fuzz-schema: schema$(EXEEXT) seed/schema.stamp
+	@mkdir -p corpus/schema
+	./schema$(EXEEXT) \
+	    -dict=schema.dict \
+	    -max_len=$(XML_MAX_LEN) \
+	    -timeout=20 \
+	    corpus/schema seed/schema
+
+# XPath fuzzer
+
+seed/xpath.stamp: genSeed$(EXEEXT)
+	@mkdir -p seed/xpath
+	@./genSeed$(EXEEXT) xpath "$(top_builddir)/test/XPath"
+	@touch seed/xpath.stamp
+
+xpath_SOURCES = xpath.c fuzz.c
+xpath_LDFLAGS = -fsanitize=fuzzer
+
+fuzz-xpath: xpath$(EXEEXT) seed/xpath.stamp
+	@mkdir -p corpus/xpath
+	./xpath$(EXEEXT) \
+	    -dict=xpath.dict \
+	    -max_len=10000 \
+	    -timeout=20 \
+	    corpus/xpath seed/xpath
+
diff --git a/third_party/libxml/src/fuzz/Makefile.in b/third_party/libxml/src/fuzz/Makefile.in
new file mode 100644
index 0000000..4dd6eba
--- /dev/null
+++ b/third_party/libxml/src/fuzz/Makefile.in
@@ -0,0 +1,969 @@
+# Makefile.in generated by automake 1.16.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+EXTRA_PROGRAMS = genSeed$(EXEEXT) html$(EXEEXT) regexp$(EXEEXT) \
+	schema$(EXEEXT) uri$(EXEEXT) xml$(EXEEXT) xpath$(EXEEXT)
+check_PROGRAMS = testFuzzer$(EXEEXT)
+subdir = fuzz
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am_genSeed_OBJECTS = genSeed.$(OBJEXT) fuzz.$(OBJEXT)
+genSeed_OBJECTS = $(am_genSeed_OBJECTS)
+genSeed_LDADD = $(LDADD)
+am__DEPENDENCIES_1 =
+genSeed_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+	$(top_builddir)/libxml2.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+am_html_OBJECTS = html.$(OBJEXT) fuzz.$(OBJEXT)
+html_OBJECTS = $(am_html_OBJECTS)
+html_LDADD = $(LDADD)
+html_DEPENDENCIES = $(am__DEPENDENCIES_1) $(top_builddir)/libxml2.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+html_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(html_LDFLAGS) $(LDFLAGS) -o $@
+am_regexp_OBJECTS = regexp.$(OBJEXT) fuzz.$(OBJEXT)
+regexp_OBJECTS = $(am_regexp_OBJECTS)
+regexp_LDADD = $(LDADD)
+regexp_DEPENDENCIES = $(am__DEPENDENCIES_1) $(top_builddir)/libxml2.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+regexp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(regexp_LDFLAGS) $(LDFLAGS) -o $@
+am_schema_OBJECTS = schema.$(OBJEXT) fuzz.$(OBJEXT)
+schema_OBJECTS = $(am_schema_OBJECTS)
+schema_LDADD = $(LDADD)
+schema_DEPENDENCIES = $(am__DEPENDENCIES_1) $(top_builddir)/libxml2.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+schema_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(schema_LDFLAGS) $(LDFLAGS) -o $@
+am_testFuzzer_OBJECTS = testFuzzer.$(OBJEXT) fuzz.$(OBJEXT)
+testFuzzer_OBJECTS = $(am_testFuzzer_OBJECTS)
+testFuzzer_LDADD = $(LDADD)
+testFuzzer_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+	$(top_builddir)/libxml2.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
+am_uri_OBJECTS = uri.$(OBJEXT) fuzz.$(OBJEXT)
+uri_OBJECTS = $(am_uri_OBJECTS)
+uri_LDADD = $(LDADD)
+uri_DEPENDENCIES = $(am__DEPENDENCIES_1) $(top_builddir)/libxml2.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+uri_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(uri_LDFLAGS) $(LDFLAGS) -o $@
+am_xml_OBJECTS = xml.$(OBJEXT) fuzz.$(OBJEXT)
+xml_OBJECTS = $(am_xml_OBJECTS)
+xml_LDADD = $(LDADD)
+xml_DEPENDENCIES = $(am__DEPENDENCIES_1) $(top_builddir)/libxml2.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+xml_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(xml_LDFLAGS) $(LDFLAGS) -o $@
+am_xpath_OBJECTS = xpath.$(OBJEXT) fuzz.$(OBJEXT)
+xpath_OBJECTS = $(am_xpath_OBJECTS)
+xpath_LDADD = $(LDADD)
+xpath_DEPENDENCIES = $(am__DEPENDENCIES_1) $(top_builddir)/libxml2.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+xpath_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(xpath_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/fuzz.Po ./$(DEPDIR)/genSeed.Po \
+	./$(DEPDIR)/html.Po ./$(DEPDIR)/regexp.Po \
+	./$(DEPDIR)/schema.Po ./$(DEPDIR)/testFuzzer.Po \
+	./$(DEPDIR)/uri.Po ./$(DEPDIR)/xml.Po ./$(DEPDIR)/xpath.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(genSeed_SOURCES) $(html_SOURCES) $(regexp_SOURCES) \
+	$(schema_SOURCES) $(testFuzzer_SOURCES) $(uri_SOURCES) \
+	$(xml_SOURCES) $(xpath_SOURCES)
+DIST_SOURCES = $(genSeed_SOURCES) $(html_SOURCES) $(regexp_SOURCES) \
+	$(schema_SOURCES) $(testFuzzer_SOURCES) $(uri_SOURCES) \
+	$(xml_SOURCES) $(xpath_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASE_THREAD_LIBS = @BASE_THREAD_LIBS@
+C14N_OBJ = @C14N_OBJ@
+CATALOG_OBJ = @CATALOG_OBJ@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+CYGWIN_EXTRA_LDFLAGS = @CYGWIN_EXTRA_LDFLAGS@
+CYGWIN_EXTRA_PYTHON_LIBADD = @CYGWIN_EXTRA_PYTHON_LIBADD@
+DEBUG_OBJ = @DEBUG_OBJ@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOCB_OBJ = @DOCB_OBJ@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_CFLAGS = @EXTRA_CFLAGS@
+FGREP = @FGREP@
+FTP_OBJ = @FTP_OBJ@
+GREP = @GREP@
+HAVE_ISINF = @HAVE_ISINF@
+HAVE_ISNAN = @HAVE_ISNAN@
+HTML_DIR = @HTML_DIR@
+HTML_OBJ = @HTML_OBJ@
+HTTP_OBJ = @HTTP_OBJ@
+ICONV_LIBS = @ICONV_LIBS@
+ICU_CFLAGS = @ICU_CFLAGS@
+ICU_LIBS = @ICU_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBXML_MAJOR_VERSION = @LIBXML_MAJOR_VERSION@
+LIBXML_MICRO_VERSION = @LIBXML_MICRO_VERSION@
+LIBXML_MINOR_VERSION = @LIBXML_MINOR_VERSION@
+LIBXML_VERSION = @LIBXML_VERSION@
+LIBXML_VERSION_EXTRA = @LIBXML_VERSION_EXTRA@
+LIBXML_VERSION_INFO = @LIBXML_VERSION_INFO@
+LIBXML_VERSION_NUMBER = @LIBXML_VERSION_NUMBER@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+LZMA_CFLAGS = @LZMA_CFLAGS@
+LZMA_LIBS = @LZMA_LIBS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MODULE_EXTENSION = @MODULE_EXTENSION@
+MODULE_PLATFORM_LIBS = @MODULE_PLATFORM_LIBS@
+MV = @MV@
+M_LIBS = @M_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PYTHON = @PYTHON@
+PYTHON_INCLUDES = @PYTHON_INCLUDES@
+PYTHON_LIBS = @PYTHON_LIBS@
+PYTHON_SITE_PACKAGES = @PYTHON_SITE_PACKAGES@
+PYTHON_SUBDIR = @PYTHON_SUBDIR@
+PYTHON_TESTS = @PYTHON_TESTS@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RDL_LIBS = @RDL_LIBS@
+READER_TEST = @READER_TEST@
+RELDATE = @RELDATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STATIC_BINARIES = @STATIC_BINARIES@
+STRIP = @STRIP@
+TAR = @TAR@
+TEST_C14N = @TEST_C14N@
+TEST_CATALOG = @TEST_CATALOG@
+TEST_DEBUG = @TEST_DEBUG@
+TEST_HTML = @TEST_HTML@
+TEST_MODULES = @TEST_MODULES@
+TEST_PATTERN = @TEST_PATTERN@
+TEST_PHTML = @TEST_PHTML@
+TEST_PUSH = @TEST_PUSH@
+TEST_REGEXPS = @TEST_REGEXPS@
+TEST_SAX = @TEST_SAX@
+TEST_SCHEMAS = @TEST_SCHEMAS@
+TEST_SCHEMATRON = @TEST_SCHEMATRON@
+TEST_THREADS = @TEST_THREADS@
+TEST_VALID = @TEST_VALID@
+TEST_VTIME = @TEST_VTIME@
+TEST_XINCLUDE = @TEST_XINCLUDE@
+TEST_XPATH = @TEST_XPATH@
+TEST_XPTR = @TEST_XPTR@
+THREAD_CFLAGS = @THREAD_CFLAGS@
+THREAD_LIBS = @THREAD_LIBS@
+VERSION = @VERSION@
+VERSION_SCRIPT_FLAGS = @VERSION_SCRIPT_FLAGS@
+WGET = @WGET@
+WIN32_EXTRA_LDFLAGS = @WIN32_EXTRA_LDFLAGS@
+WIN32_EXTRA_LIBADD = @WIN32_EXTRA_LIBADD@
+WIN32_EXTRA_PYTHON_LIBADD = @WIN32_EXTRA_PYTHON_LIBADD@
+WITH_C14N = @WITH_C14N@
+WITH_CATALOG = @WITH_CATALOG@
+WITH_DEBUG = @WITH_DEBUG@
+WITH_DOCB = @WITH_DOCB@
+WITH_FTP = @WITH_FTP@
+WITH_HTML = @WITH_HTML@
+WITH_HTTP = @WITH_HTTP@
+WITH_ICONV = @WITH_ICONV@
+WITH_ICU = @WITH_ICU@
+WITH_ISO8859X = @WITH_ISO8859X@
+WITH_LEGACY = @WITH_LEGACY@
+WITH_LZMA = @WITH_LZMA@
+WITH_MEM_DEBUG = @WITH_MEM_DEBUG@
+WITH_MODULES = @WITH_MODULES@
+WITH_OUTPUT = @WITH_OUTPUT@
+WITH_PATTERN = @WITH_PATTERN@
+WITH_PUSH = @WITH_PUSH@
+WITH_READER = @WITH_READER@
+WITH_REGEXPS = @WITH_REGEXPS@
+WITH_RUN_DEBUG = @WITH_RUN_DEBUG@
+WITH_SAX1 = @WITH_SAX1@
+WITH_SCHEMAS = @WITH_SCHEMAS@
+WITH_SCHEMATRON = @WITH_SCHEMATRON@
+WITH_THREADS = @WITH_THREADS@
+WITH_THREAD_ALLOC = @WITH_THREAD_ALLOC@
+WITH_TREE = @WITH_TREE@
+WITH_TRIO = @WITH_TRIO@
+WITH_VALID = @WITH_VALID@
+WITH_WRITER = @WITH_WRITER@
+WITH_XINCLUDE = @WITH_XINCLUDE@
+WITH_XPATH = @WITH_XPATH@
+WITH_XPTR = @WITH_XPTR@
+WITH_ZLIB = @WITH_ZLIB@
+XINCLUDE_OBJ = @XINCLUDE_OBJ@
+XMLLINT = @XMLLINT@
+XML_CFLAGS = @XML_CFLAGS@
+XML_INCLUDEDIR = @XML_INCLUDEDIR@
+XML_LIBDIR = @XML_LIBDIR@
+XML_LIBS = @XML_LIBS@
+XML_LIBTOOLLIBS = @XML_LIBTOOLLIBS@
+XML_PRIVATE_LIBS = @XML_PRIVATE_LIBS@
+XPATH_OBJ = @XPATH_OBJ@
+XPTR_OBJ = @XPTR_OBJ@
+XSLTPROC = @XSLTPROC@
+Z_CFLAGS = @Z_CFLAGS@
+Z_LIBS = @Z_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = -Wno-syntax
+CLEANFILES = $(EXTRA_PROGRAMS)
+AM_CPPFLAGS = -I$(top_srcdir)/include
+DEPENDENCIES = $(top_builddir)/libxml2.la
+LDADD = $(STATIC_BINARIES) $(top_builddir)/libxml2.la $(THREAD_LIBS) $(Z_LIBS) $(LZMA_LIBS) $(ICONV_LIBS) $(M_LIBS) $(WIN32_EXTRA_LIBADD)
+XML_MAX_LEN = 80000
+# Single quotes to avoid wildcard expansion by the shell
+XML_SEED_CORPUS_SRC = \
+    '$(top_srcdir)/test/*' \
+    '$(top_srcdir)/test/errors/*.xml' \
+    '$(top_srcdir)/test/errors10/*.xml' \
+    '$(top_srcdir)/test/namespaces/*' \
+    '$(top_srcdir)/test/valid/*.xml' \
+    '$(top_srcdir)/test/VC/*' \
+    '$(top_srcdir)/test/VCM/*' \
+    '$(top_srcdir)/test/XInclude/docs/*' \
+    '$(top_srcdir)/test/xmlid/*'
+
+testFuzzer_SOURCES = testFuzzer.c fuzz.c
+
+# Seed corpus
+genSeed_SOURCES = genSeed.c fuzz.c
+xml_SOURCES = xml.c fuzz.c
+xml_LDFLAGS = -fsanitize=fuzzer
+html_SOURCES = html.c fuzz.c
+html_LDFLAGS = -fsanitize=fuzzer
+
+# Regexp fuzzer
+regexp_SOURCES = regexp.c fuzz.c
+regexp_LDFLAGS = -fsanitize=fuzzer
+
+# URI fuzzer
+uri_SOURCES = uri.c fuzz.c
+uri_LDFLAGS = -fsanitize=fuzzer
+schema_SOURCES = schema.c fuzz.c
+schema_LDFLAGS = -fsanitize=fuzzer
+xpath_SOURCES = xpath.c fuzz.c
+xpath_LDFLAGS = -fsanitize=fuzzer
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign fuzz/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign fuzz/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-checkPROGRAMS:
+	@list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+
+genSeed$(EXEEXT): $(genSeed_OBJECTS) $(genSeed_DEPENDENCIES) $(EXTRA_genSeed_DEPENDENCIES) 
+	@rm -f genSeed$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(genSeed_OBJECTS) $(genSeed_LDADD) $(LIBS)
+
+html$(EXEEXT): $(html_OBJECTS) $(html_DEPENDENCIES) $(EXTRA_html_DEPENDENCIES) 
+	@rm -f html$(EXEEXT)
+	$(AM_V_CCLD)$(html_LINK) $(html_OBJECTS) $(html_LDADD) $(LIBS)
+
+regexp$(EXEEXT): $(regexp_OBJECTS) $(regexp_DEPENDENCIES) $(EXTRA_regexp_DEPENDENCIES) 
+	@rm -f regexp$(EXEEXT)
+	$(AM_V_CCLD)$(regexp_LINK) $(regexp_OBJECTS) $(regexp_LDADD) $(LIBS)
+
+schema$(EXEEXT): $(schema_OBJECTS) $(schema_DEPENDENCIES) $(EXTRA_schema_DEPENDENCIES) 
+	@rm -f schema$(EXEEXT)
+	$(AM_V_CCLD)$(schema_LINK) $(schema_OBJECTS) $(schema_LDADD) $(LIBS)
+
+testFuzzer$(EXEEXT): $(testFuzzer_OBJECTS) $(testFuzzer_DEPENDENCIES) $(EXTRA_testFuzzer_DEPENDENCIES) 
+	@rm -f testFuzzer$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(testFuzzer_OBJECTS) $(testFuzzer_LDADD) $(LIBS)
+
+uri$(EXEEXT): $(uri_OBJECTS) $(uri_DEPENDENCIES) $(EXTRA_uri_DEPENDENCIES) 
+	@rm -f uri$(EXEEXT)
+	$(AM_V_CCLD)$(uri_LINK) $(uri_OBJECTS) $(uri_LDADD) $(LIBS)
+
+xml$(EXEEXT): $(xml_OBJECTS) $(xml_DEPENDENCIES) $(EXTRA_xml_DEPENDENCIES) 
+	@rm -f xml$(EXEEXT)
+	$(AM_V_CCLD)$(xml_LINK) $(xml_OBJECTS) $(xml_LDADD) $(LIBS)
+
+xpath$(EXEEXT): $(xpath_OBJECTS) $(xpath_DEPENDENCIES) $(EXTRA_xpath_DEPENDENCIES) 
+	@rm -f xpath$(EXEEXT)
+	$(AM_V_CCLD)$(xpath_LINK) $(xpath_OBJECTS) $(xpath_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/genSeed.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/html.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regexp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/schema.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testFuzzer.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uri.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xpath.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+	@$(MKDIR_P) $(@D)
+	@echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+	mostlyclean-am
+
+distclean: distclean-am
+		-rm -f ./$(DEPDIR)/fuzz.Po
+	-rm -f ./$(DEPDIR)/genSeed.Po
+	-rm -f ./$(DEPDIR)/html.Po
+	-rm -f ./$(DEPDIR)/regexp.Po
+	-rm -f ./$(DEPDIR)/schema.Po
+	-rm -f ./$(DEPDIR)/testFuzzer.Po
+	-rm -f ./$(DEPDIR)/uri.Po
+	-rm -f ./$(DEPDIR)/xml.Po
+	-rm -f ./$(DEPDIR)/xpath.Po
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+		-rm -f ./$(DEPDIR)/fuzz.Po
+	-rm -f ./$(DEPDIR)/genSeed.Po
+	-rm -f ./$(DEPDIR)/html.Po
+	-rm -f ./$(DEPDIR)/regexp.Po
+	-rm -f ./$(DEPDIR)/schema.Po
+	-rm -f ./$(DEPDIR)/testFuzzer.Po
+	-rm -f ./$(DEPDIR)/uri.Po
+	-rm -f ./$(DEPDIR)/xml.Po
+	-rm -f ./$(DEPDIR)/xpath.Po
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+	clean-checkPROGRAMS clean-generic clean-libtool cscopelist-am \
+	ctags ctags-am distclean distclean-compile distclean-generic \
+	distclean-libtool distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+.PHONY: tests corpus clean-corpus
+
+corpus: seed/html.stamp seed/schema.stamp seed/xml.stamp seed/xpath.stamp
+
+tests: testFuzzer$(EXEEXT) corpus
+	@echo "## Running fuzzer tests"
+	@./testFuzzer$(EXEEXT)
+
+clean-corpus:
+	rm -rf seed/html.stamp seed/html
+	rm -rf seed/schema.stamp seed/schema
+	rm -rf seed/xml.stamp seed/xml
+	rm -rf seed/xpath.stamp seed/xpath
+
+# XML fuzzer
+
+seed/xml.stamp: genSeed$(EXEEXT)
+	@mkdir -p seed/xml
+	@./genSeed$(EXEEXT) xml $(XML_SEED_CORPUS_SRC)
+	@touch seed/xml.stamp
+
+fuzz-xml: xml$(EXEEXT) seed/xml.stamp
+	@mkdir -p corpus/xml
+	./xml$(EXEEXT) \
+	    -dict=xml.dict \
+	    -max_len=$(XML_MAX_LEN) \
+	    -timeout=20 \
+	    corpus/xml seed/xml
+
+# HTML fuzzer
+
+seed/html.stamp: genSeed$(EXEEXT)
+	@mkdir -p seed/html
+	@./genSeed$(EXEEXT) html '$(top_srcdir)/test/HTML/*'
+	@touch seed/html.stamp
+
+fuzz-html: html$(EXEEXT) seed/html.stamp
+	@mkdir -p corpus/html
+	./html$(EXEEXT) \
+	    -dict=html.dict \
+	    -max_len=1000000 \
+	    -timeout=20 \
+	    corpus/html seed/html
+
+fuzz-regexp: regexp$(EXEEXT)
+	@mkdir -p corpus/regexp
+	./regexp$(EXEEXT) \
+	    -dict=regexp.dict \
+	    -max_len=200 \
+	    -timeout=5 \
+	    corpus/regexp $(srcdir)/seed/regexp
+
+fuzz-uri: uri$(EXEEXT)
+	@mkdir -p corpus/uri
+	./uri$(EXEEXT) \
+	    -max_len=10000 \
+	    -timeout=5 \
+	    corpus/uri $(srcdir)/seed/uri
+
+# XML Schema fuzzer
+
+seed/schema.stamp: genSeed$(EXEEXT)
+	@mkdir -p seed/schema
+	@./genSeed$(EXEEXT) schema '$(top_srcdir)/test/schemas/*.xsd'
+	@touch seed/schema.stamp
+
+fuzz-schema: schema$(EXEEXT) seed/schema.stamp
+	@mkdir -p corpus/schema
+	./schema$(EXEEXT) \
+	    -dict=schema.dict \
+	    -max_len=$(XML_MAX_LEN) \
+	    -timeout=20 \
+	    corpus/schema seed/schema
+
+# XPath fuzzer
+
+seed/xpath.stamp: genSeed$(EXEEXT)
+	@mkdir -p seed/xpath
+	@./genSeed$(EXEEXT) xpath "$(top_builddir)/test/XPath"
+	@touch seed/xpath.stamp
+
+fuzz-xpath: xpath$(EXEEXT) seed/xpath.stamp
+	@mkdir -p corpus/xpath
+	./xpath$(EXEEXT) \
+	    -dict=xpath.dict \
+	    -max_len=10000 \
+	    -timeout=20 \
+	    corpus/xpath seed/xpath
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/third_party/libxml/src/fuzz/README b/third_party/libxml/src/fuzz/README
new file mode 100644
index 0000000..f675ad82
--- /dev/null
+++ b/third_party/libxml/src/fuzz/README
@@ -0,0 +1,19 @@
+libFuzzer instructions for libxml2
+==================================
+
+Set compiler and options:
+
+    export CC=clang
+    export CFLAGS="-g -fsanitize=fuzzer-no-link,address,undefined \
+        -fno-sanitize-recover=all \
+        -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION"
+
+Build libxml2 with instrumentation:
+
+    ./configure --without-python
+    make
+
+Run fuzzers:
+
+    make -C fuzz fuzz-xml
+
diff --git a/third_party/libxml/src/fuzz/fuzz.c b/third_party/libxml/src/fuzz/fuzz.c
new file mode 100644
index 0000000..b5dfa18
--- /dev/null
+++ b/third_party/libxml/src/fuzz/fuzz.c
@@ -0,0 +1,349 @@
+/*
+ * fuzz.c: Common functions for fuzzing.
+ *
+ * See Copyright for the status of this software.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <libxml/hash.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/tree.h>
+#include <libxml/xmlIO.h>
+#include "fuzz.h"
+
+typedef struct {
+    const char *data;
+    size_t size;
+} xmlFuzzEntityInfo;
+
+/* Single static instance for now */
+static struct {
+    /* Original data */
+    const char *data;
+    size_t size;
+
+    /* Remaining data */
+    const char *ptr;
+    size_t remaining;
+
+    /* Buffer for unescaped strings */
+    char *outBuf;
+    char *outPtr; /* Free space at end of buffer */
+
+    xmlHashTablePtr entities; /* Maps URLs to xmlFuzzEntityInfos */
+
+    /* The first entity is the main entity. */
+    const char *mainUrl;
+    xmlFuzzEntityInfo *mainEntity;
+} fuzzData;
+
+/**
+ * xmlFuzzErrorFunc:
+ *
+ * An error function that simply discards all errors.
+ */
+void
+xmlFuzzErrorFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg ATTRIBUTE_UNUSED,
+                 ...) {
+}
+
+/**
+ * xmlFuzzDataInit:
+ *
+ * Initialize fuzz data provider.
+ */
+void
+xmlFuzzDataInit(const char *data, size_t size) {
+    fuzzData.data = data;
+    fuzzData.size = size;
+    fuzzData.ptr = data;
+    fuzzData.remaining = size;
+
+    fuzzData.outBuf = xmlMalloc(size + 1);
+    fuzzData.outPtr = fuzzData.outBuf;
+
+    fuzzData.entities = xmlHashCreate(8);
+    fuzzData.mainUrl = NULL;
+    fuzzData.mainEntity = NULL;
+}
+
+/**
+ * xmlFuzzDataFree:
+ *
+ * Cleanup fuzz data provider.
+ */
+void
+xmlFuzzDataCleanup(void) {
+    xmlFree(fuzzData.outBuf);
+    xmlHashFree(fuzzData.entities, xmlHashDefaultDeallocator);
+}
+
+/**
+ * xmlFuzzReadInt:
+ * @size:  size of string in bytes
+ *
+ * Read an integer from the fuzz data.
+ */
+int
+xmlFuzzReadInt() {
+    int ret;
+
+    if (fuzzData.remaining < sizeof(int))
+        return(0);
+    memcpy(&ret, fuzzData.ptr, sizeof(int));
+    fuzzData.ptr += sizeof(int);
+    fuzzData.remaining -= sizeof(int);
+
+    return ret;
+}
+
+/**
+ * xmlFuzzReadRemaining:
+ * @size:  size of string in bytes
+ *
+ * Read remaining bytes from fuzz data.
+ */
+const char *
+xmlFuzzReadRemaining(size_t *size) {
+    const char *ret = fuzzData.ptr;
+
+    *size = fuzzData.remaining;
+    fuzzData.ptr += fuzzData.remaining;
+    fuzzData.remaining = 0;
+
+    return(ret);
+}
+
+/*
+ * xmlFuzzWriteString:
+ * @out:  output file
+ * @str:  string to write
+ *
+ * Write a random-length string to file in a format similar to
+ * FuzzedDataProvider. Backslash followed by newline marks the end of the
+ * string. Two backslashes are used to escape a backslash.
+ */
+void
+xmlFuzzWriteString(FILE *out, const char *str) {
+    for (; *str; str++) {
+        int c = (unsigned char) *str;
+        putc(c, out);
+        if (c == '\\')
+            putc(c, out);
+    }
+    putc('\\', out);
+    putc('\n', out);
+}
+
+/**
+ * xmlFuzzReadString:
+ * @size:  size of string in bytes
+ *
+ * Read a random-length string from the fuzz data.
+ *
+ * The format is similar to libFuzzer's FuzzedDataProvider but treats
+ * backslash followed by newline as end of string. This makes the fuzz data
+ * more readable. A backslash character is escaped with another backslash.
+ *
+ * Returns a zero-terminated string or NULL if the fuzz data is exhausted.
+ */
+const char *
+xmlFuzzReadString(size_t *size) {
+    const char *out = fuzzData.outPtr;
+
+    while (fuzzData.remaining > 0) {
+        int c = *fuzzData.ptr++;
+        fuzzData.remaining--;
+
+        if ((c == '\\') && (fuzzData.remaining > 0)) {
+            int c2 = *fuzzData.ptr;
+
+            if (c2 == '\n') {
+                fuzzData.ptr++;
+                fuzzData.remaining--;
+                *size = fuzzData.outPtr - out;
+                *fuzzData.outPtr++ = '\0';
+                return(out);
+            }
+            if (c2 == '\\') {
+                fuzzData.ptr++;
+                fuzzData.remaining--;
+            }
+        }
+
+        *fuzzData.outPtr++ = c;
+    }
+
+    if (fuzzData.outPtr > out) {
+        *size = fuzzData.outPtr - out;
+        *fuzzData.outPtr++ = '\0';
+        return(out);
+    }
+
+    return(NULL);
+}
+
+/**
+ * xmlFuzzReadEntities:
+ *
+ * Read entities like the main XML file, external DTDs, external parsed
+ * entities from fuzz data.
+ */
+void
+xmlFuzzReadEntities(void) {
+    size_t num = 0;
+
+    while (1) {
+        const char *url, *entity;
+        size_t urlSize, entitySize;
+        xmlFuzzEntityInfo *entityInfo;
+        
+        url = xmlFuzzReadString(&urlSize);
+        if (url == NULL) break;
+
+        entity = xmlFuzzReadString(&entitySize);
+        if (entity == NULL) break;
+
+        if (xmlHashLookup(fuzzData.entities, (xmlChar *)url) == NULL) {
+            entityInfo = xmlMalloc(sizeof(xmlFuzzEntityInfo));
+            entityInfo->data = entity;
+            entityInfo->size = entitySize;
+
+            xmlHashAddEntry(fuzzData.entities, (xmlChar *)url, entityInfo);
+
+            if (num == 0) {
+                fuzzData.mainUrl = url;
+                fuzzData.mainEntity = entityInfo;
+            }
+
+            num++;
+        }
+    }
+}
+
+/**
+ * xmlFuzzMainUrl:
+ *
+ * Returns the main URL.
+ */
+const char *
+xmlFuzzMainUrl(void) {
+    return(fuzzData.mainUrl);
+}
+
+/**
+ * xmlFuzzMainEntity:
+ * @size:  size of the main entity in bytes
+ *
+ * Returns the main entity.
+ */
+const char *
+xmlFuzzMainEntity(size_t *size) {
+    if (fuzzData.mainEntity == NULL)
+        return(NULL);
+    *size = fuzzData.mainEntity->size;
+    return(fuzzData.mainEntity->data);
+}
+
+/**
+ * xmlFuzzEntityLoader:
+ *
+ * The entity loader for fuzz data.
+ */
+xmlParserInputPtr
+xmlFuzzEntityLoader(const char *URL, const char *ID ATTRIBUTE_UNUSED,
+                    xmlParserCtxtPtr ctxt) {
+    xmlParserInputPtr input;
+    xmlFuzzEntityInfo *entity;
+
+    if (URL == NULL)
+        return(NULL);
+    entity = xmlHashLookup(fuzzData.entities, (xmlChar *) URL);
+    if (entity == NULL)
+        return(NULL);
+
+    input = xmlNewInputStream(ctxt);
+    input->filename = NULL;
+    input->buf = xmlParserInputBufferCreateMem(entity->data, entity->size,
+                                               XML_CHAR_ENCODING_NONE);
+    input->base = input->cur = xmlBufContent(input->buf->buffer);
+    input->end = input->base + entity->size;
+
+    return input;
+}
+
+/**
+ * xmlFuzzExtractStrings:
+ *
+ * Extract C strings from input data. Use exact-size allocations to detect
+ * potential memory errors.
+ */
+size_t
+xmlFuzzExtractStrings(const char *data, size_t size, char **strings,
+                      size_t numStrings) {
+    const char *start = data;
+    const char *end = data + size;
+    size_t i = 0, ret;
+
+    while (i < numStrings) {
+        size_t strSize = end - start;
+        const char *zero = memchr(start, 0, strSize);
+
+        if (zero != NULL)
+            strSize = zero - start;
+
+        strings[i] = xmlMalloc(strSize + 1);
+        memcpy(strings[i], start, strSize);
+        strings[i][strSize] = '\0';
+
+        i++;
+        if (zero != NULL)
+            start = zero + 1;
+        else
+            break;
+    }
+
+    ret = i;
+
+    while (i < numStrings) {
+        strings[i] = NULL;
+        i++;
+    }
+
+    return(ret);
+}
+
+char *
+xmlSlurpFile(const char *path, size_t *sizeRet) {
+    FILE *file;
+    struct stat statbuf;
+    char *data;
+    size_t size;
+
+    if ((stat(path, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode)))
+        return(NULL);
+    size = statbuf.st_size;
+    file = fopen(path, "rb");
+    if (file == NULL)
+        return(NULL);
+    data = xmlMalloc(size + 1);
+    if (data != NULL) {
+        if (fread(data, 1, size, file) != size) {
+            xmlFree(data);
+            data = NULL;
+        } else {
+            data[size] = 0;
+            if (sizeRet != NULL)
+                *sizeRet = size;
+        }
+    }
+    fclose(file);
+
+    return(data);
+}
+
diff --git a/third_party/libxml/src/fuzz/genSeed.c b/third_party/libxml/src/fuzz/genSeed.c
new file mode 100644
index 0000000..68fb87a
--- /dev/null
+++ b/third_party/libxml/src/fuzz/genSeed.c
@@ -0,0 +1,407 @@
+/*
+ * xmlSeed.c: Generate the XML seed corpus for fuzzing.
+ *
+ * See Copyright for the status of this software.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <glob.h>
+#include <libgen.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/xinclude.h>
+#include <libxml/xmlschemas.h>
+#include "fuzz.h"
+
+#define PATH_SIZE 500
+#define SEED_BUF_SIZE 16384
+#define EXPR_SIZE 4500
+
+typedef int
+(*fileFunc)(const char *base, FILE *out);
+
+typedef int
+(*mainFunc)(const char *arg);
+
+static struct {
+    FILE *out;
+    xmlHashTablePtr entities; /* Maps URLs to xmlFuzzEntityInfos */
+    xmlExternalEntityLoader oldLoader;
+    fileFunc processFile;
+    const char *fuzzer;
+    int counter;
+    char cwd[PATH_SIZE];
+} globalData;
+
+/*
+ * A custom entity loader that writes all external DTDs or entities to a
+ * single file in the format expected by xmlFuzzEntityLoader.
+ */
+static xmlParserInputPtr
+fuzzEntityRecorder(const char *URL, const char *ID,
+                      xmlParserCtxtPtr ctxt) {
+    xmlParserInputPtr in;
+    static const int chunkSize = 16384;
+    int len;
+
+    in = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+    if (in == NULL)
+        return(NULL);
+
+    if (globalData.entities == NULL) {
+        globalData.entities = xmlHashCreate(4);
+    } else if (xmlHashLookup(globalData.entities,
+                             (const xmlChar *) URL) != NULL) {
+        return(in);
+    }
+
+    do {
+        len = xmlParserInputBufferGrow(in->buf, chunkSize);
+        if (len < 0) {
+            fprintf(stderr, "Error reading %s\n", URL);
+            xmlFreeInputStream(in);
+            return(NULL);
+        }
+    } while (len > 0);
+
+    xmlFuzzWriteString(globalData.out, URL);
+    xmlFuzzWriteString(globalData.out,
+                       (char *) xmlBufContent(in->buf->buffer));
+
+    xmlFreeInputStream(in);
+
+    xmlHashAddEntry(globalData.entities, (const xmlChar *) URL, NULL);
+
+    return(xmlNoNetExternalEntityLoader(URL, ID, ctxt));
+}
+
+static void
+fuzzRecorderInit(FILE *out) {
+    globalData.out = out;
+    globalData.entities = xmlHashCreate(8);
+    globalData.oldLoader = xmlGetExternalEntityLoader();
+    xmlSetExternalEntityLoader(fuzzEntityRecorder);
+}
+
+static void
+fuzzRecorderCleanup() {
+    xmlSetExternalEntityLoader(globalData.oldLoader);
+    xmlHashFree(globalData.entities, xmlHashDefaultDeallocator);
+    globalData.out = NULL;
+    globalData.entities = NULL;
+    globalData.oldLoader = NULL;
+}
+
+static int
+processXml(const char *docFile, FILE *out) {
+    int opts = XML_PARSE_NOENT | XML_PARSE_DTDLOAD;
+    xmlDocPtr doc;
+
+    fwrite(&opts, sizeof(opts), 1, out);
+
+    fuzzRecorderInit(out);
+
+    doc = xmlReadFile(docFile, NULL, opts);
+    xmlXIncludeProcessFlags(doc, opts);
+    xmlFreeDoc(doc);
+
+    fuzzRecorderCleanup();
+
+    return(0);
+}
+
+static int
+processHtml(const char *docFile, FILE *out) {
+    char buf[SEED_BUF_SIZE];
+    FILE *file;
+    size_t size;
+    int opts = 0;
+
+    fwrite(&opts, sizeof(opts), 1, out);
+
+    /* Copy file */
+    file = fopen(docFile, "rb");
+    if (file == NULL) {
+        fprintf(stderr, "couldn't open %s\n", docFile);
+        return(0);
+    }
+    do {
+        size = fread(buf, 1, SEED_BUF_SIZE, file);
+        if (size > 0)
+            fwrite(buf, 1, size, out);
+    } while (size == SEED_BUF_SIZE);
+    fclose(file);
+
+    return(0);
+}
+
+static int
+processSchema(const char *docFile, FILE *out) {
+    xmlSchemaPtr schema;
+    xmlSchemaParserCtxtPtr pctxt;
+
+    fuzzRecorderInit(out);
+
+    pctxt = xmlSchemaNewParserCtxt(docFile);
+    xmlSchemaSetParserErrors(pctxt, xmlFuzzErrorFunc, xmlFuzzErrorFunc, NULL);
+    schema = xmlSchemaParse(pctxt);
+    xmlSchemaFreeParserCtxt(pctxt);
+    xmlSchemaFree(schema);
+
+    fuzzRecorderCleanup();
+
+    return(0);
+}
+
+static int
+processPattern(const char *pattern) {
+    glob_t globbuf;
+    int ret = 0;
+    int res, i;
+
+    res = glob(pattern, 0, NULL, &globbuf);
+    if (res == GLOB_NOMATCH)
+        return(0);
+    if (res != 0) {
+        fprintf(stderr, "couldn't match pattern %s\n", pattern);
+        return(-1);
+    }
+
+    for (i = 0; i < globbuf.gl_pathc; i++) {
+        struct stat statbuf;
+        char outPath[PATH_SIZE];
+        char *dirBuf = NULL;
+        char *baseBuf = NULL;
+        const char *path, *dir, *base;
+        FILE *out = NULL;
+        int dirChanged = 0;
+        size_t size;
+
+        path = globbuf.gl_pathv[i];
+
+        if ((stat(path, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode)))
+            continue;
+
+        dirBuf = (char *) xmlCharStrdup(path);
+        baseBuf = (char *) xmlCharStrdup(path);
+        if ((dirBuf == NULL) || (baseBuf == NULL)) {
+            fprintf(stderr, "memory allocation failed\n");
+            ret = -1;
+            goto error;
+        }
+        dir = dirname(dirBuf);
+        base = basename(baseBuf);
+
+        size = snprintf(outPath, sizeof(outPath), "seed/%s/%s",
+                        globalData.fuzzer, base);
+        if (size >= PATH_SIZE) {
+            fprintf(stderr, "creating path failed\n");
+            ret = -1;
+            goto error;
+        }
+        out = fopen(outPath, "wb");
+        if (out == NULL) {
+            fprintf(stderr, "couldn't open %s for writing\n", outPath);
+            ret = -1;
+            goto error;
+        }
+        if (chdir(dir) != 0) {
+            fprintf(stderr, "couldn't chdir to %s\n", dir);
+            ret = -1;
+            goto error;
+        }
+        dirChanged = 1;
+        if (globalData.processFile(base, out) != 0)
+            ret = -1;
+
+error:
+        if (out != NULL)
+            fclose(out);
+        xmlFree(dirBuf);
+        xmlFree(baseBuf);
+        if ((dirChanged) && (chdir(globalData.cwd) != 0)) {
+            fprintf(stderr, "couldn't chdir to %s\n", globalData.cwd);
+            ret = -1;
+            break;
+        }
+    }
+
+    globfree(&globbuf);
+    return(ret);
+}
+
+static int
+processXPath(const char *testDir, const char *prefix, const char *name,
+             const char *data, const char *subdir, int xptr) {
+    char pattern[PATH_SIZE];
+    glob_t globbuf;
+    size_t i, size;
+    int ret = 0, res;
+
+    size = snprintf(pattern, sizeof(pattern), "%s/%s/%s*",
+                    testDir, subdir, prefix);
+    if (size >= PATH_SIZE)
+        return(-1);
+    res = glob(pattern, 0, NULL, &globbuf);
+    if (res == GLOB_NOMATCH)
+        return(0);
+    if (res != 0) {
+        fprintf(stderr, "couldn't match pattern %s\n", pattern);
+        return(-1);
+    }
+
+    for (i = 0; i < globbuf.gl_pathc; i++) {
+        char *path = globbuf.gl_pathv[i];
+        struct stat statbuf;
+        FILE *in;
+        char expr[EXPR_SIZE];
+
+        if ((stat(path, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode)))
+            continue;
+
+        in = fopen(path, "rb");
+        if (in == NULL) {
+            ret = -1;
+            continue;
+        }
+
+        while (fgets(expr, EXPR_SIZE, in) > 0) {
+            char outPath[PATH_SIZE];
+            FILE *out;
+            int j;
+
+            for (j = 0; expr[j] != 0; j++)
+                if (expr[j] == '\r' || expr[j] == '\n')
+                    break;
+            expr[j] = 0;
+
+            size = snprintf(outPath, sizeof(outPath), "seed/xpath/%s-%d",
+                            name, globalData.counter);
+            if (size >= PATH_SIZE) {
+                ret = -1;
+                continue;
+            }
+            out = fopen(outPath, "wb");
+            if (out == NULL) {
+                ret = -1;
+                continue;
+            }
+
+            if (xptr) {
+                xmlFuzzWriteString(out, expr);
+            } else {
+                char xptrExpr[EXPR_SIZE+100];
+
+                /* Wrap XPath expressions as XPointer */
+                snprintf(xptrExpr, sizeof(xptrExpr), "xpointer(%s)", expr);
+                xmlFuzzWriteString(out, xptrExpr);
+            }
+
+            xmlFuzzWriteString(out, data);
+
+            fclose(out);
+            globalData.counter++;
+        }
+
+        fclose(in);
+    }
+
+    globfree(&globbuf);
+
+    return(ret);
+}
+
+int
+processXPathDir(const char *testDir) {
+    char pattern[PATH_SIZE];
+    glob_t globbuf;
+    size_t i, size;
+    int ret = 0;
+
+    globalData.counter = 1;
+    if (processXPath(testDir, "", "expr", "<d></d>", "expr", 0) != 0)
+        ret = -1;
+
+    size = snprintf(pattern, sizeof(pattern), "%s/docs/*", testDir);
+    if (size >= PATH_SIZE)
+        return(1);
+    if (glob(pattern, 0, NULL, &globbuf) != 0)
+        return(1);
+
+    for (i = 0; i < globbuf.gl_pathc; i++) {
+        char *path = globbuf.gl_pathv[i];
+        char *data;
+        const char *docFile;
+
+        data = xmlSlurpFile(path, NULL);
+        if (data == NULL) {
+            ret = -1;
+            continue;
+        }
+        docFile = basename(path);
+
+        globalData.counter = 1;
+        if (processXPath(testDir, docFile, docFile, data, "tests", 0) != 0)
+            ret = -1;
+        if (processXPath(testDir, docFile, docFile, data, "xptr", 1) != 0)
+            ret = -1;
+
+        xmlFree(data);
+    }
+
+    globfree(&globbuf);
+
+    return(ret);
+}
+
+int
+main(int argc, const char **argv) {
+    mainFunc processArg = processPattern;
+    const char *fuzzer;
+    int ret = 0;
+    int xpath = 0;
+    int i;
+
+    if (argc < 3) {
+        fprintf(stderr, "usage: seed [FUZZER] [PATTERN...]\n");
+        return(1);
+    }
+
+    xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
+
+    fuzzer = argv[1];
+    if (strcmp(fuzzer, "html") == 0) {
+        globalData.processFile = processHtml;
+    } else if (strcmp(fuzzer, "schema") == 0) {
+        globalData.processFile = processSchema;
+    } else if (strcmp(fuzzer, "xml") == 0) {
+        globalData.processFile = processXml;
+    } else if (strcmp(fuzzer, "xpath") == 0) {
+        processArg = processXPathDir;
+    } else {
+        fprintf(stderr, "unknown fuzzer %s\n", fuzzer);
+        return(1);
+    }
+    globalData.fuzzer = fuzzer;
+
+    if (getcwd(globalData.cwd, PATH_SIZE) == NULL) {
+        fprintf(stderr, "couldn't get current directory\n");
+        return(1);
+    }
+
+    for (i = 2; i < argc; i++)
+        processArg(argv[i]);
+
+    return(ret);
+}
+
diff --git a/third_party/libxml/src/fuzz/html.c b/third_party/libxml/src/fuzz/html.c
new file mode 100644
index 0000000..d212c1f
--- /dev/null
+++ b/third_party/libxml/src/fuzz/html.c
@@ -0,0 +1,70 @@
+/*
+ * html.c: a libFuzzer target to test several HTML parser interfaces.
+ *
+ * See Copyright for the status of this software.
+ */
+
+#include <libxml/HTMLparser.h>
+#include <libxml/HTMLtree.h>
+#include "fuzz.h"
+
+int
+LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
+                     char ***argv ATTRIBUTE_UNUSED) {
+    xmlInitParser();
+    xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
+
+    return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(const char *data, size_t size) {
+    static const size_t maxChunkSize = 128;
+    htmlDocPtr doc;
+    htmlParserCtxtPtr ctxt;
+    xmlChar *out;
+    const char *docBuffer;
+    size_t docSize, consumed, chunkSize;
+    int opts, outSize;
+
+    xmlFuzzDataInit(data, size);
+    opts = xmlFuzzReadInt();
+
+    docBuffer = xmlFuzzReadRemaining(&docSize);
+    if (docBuffer == NULL) {
+        xmlFuzzDataCleanup();
+        return(0);
+    }
+
+    /* Pull parser */
+
+    doc = htmlReadMemory(docBuffer, docSize, NULL, NULL, opts);
+    /* Also test the serializer. */
+    htmlDocDumpMemory(doc, &out, &outSize);
+    xmlFree(out);
+    xmlFreeDoc(doc);
+
+    /* Push parser */
+
+    ctxt = htmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL,
+                                    XML_CHAR_ENCODING_NONE);
+    htmlCtxtUseOptions(ctxt, opts);
+
+    for (consumed = 0; consumed < docSize; consumed += chunkSize) {
+        chunkSize = docSize - consumed;
+        if (chunkSize > maxChunkSize)
+            chunkSize = maxChunkSize;
+        htmlParseChunk(ctxt, docBuffer + consumed, chunkSize, 0);
+    }
+
+    htmlParseChunk(ctxt, NULL, 0, 1);
+    xmlFreeDoc(ctxt->myDoc);
+    htmlFreeParserCtxt(ctxt);
+
+    /* Cleanup */
+
+    xmlFuzzDataCleanup();
+
+    return(0);
+}
+
diff --git a/third_party/libxml/src/fuzz/regexp.c b/third_party/libxml/src/fuzz/regexp.c
new file mode 100644
index 0000000..3b35671
--- /dev/null
+++ b/third_party/libxml/src/fuzz/regexp.c
@@ -0,0 +1,43 @@
+/*
+ * regexp.c: a libFuzzer target to test the regexp module.
+ *
+ * See Copyright for the status of this software.
+ */
+
+#include <libxml/xmlregexp.h>
+#include "fuzz.h"
+
+int
+LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
+                     char ***argv ATTRIBUTE_UNUSED) {
+    xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
+
+    return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(const char *data, size_t size) {
+    xmlRegexpPtr regexp;
+    char *str[2] = { NULL, NULL };
+    size_t numStrings;
+
+    numStrings = xmlFuzzExtractStrings(data, size, str, 2);
+
+    /* CUR_SCHAR doesn't handle invalid UTF-8 and may cause infinite loops. */
+    if (xmlCheckUTF8(BAD_CAST str[0]) != 0) {
+        regexp = xmlRegexpCompile(BAD_CAST str[0]);
+        /* xmlRegexpExec has pathological performance in too many cases. */
+#if 0
+        if ((regexp != NULL) && (numStrings >= 2)) {
+            xmlRegexpExec(regexp, BAD_CAST str[1]);
+        }
+#endif
+        xmlRegFreeRegexp(regexp);
+    }
+
+    xmlFree(str[0]);
+    xmlFree(str[1]);
+
+    return 0;
+}
+
diff --git a/third_party/libxml/src/fuzz/schema.c b/third_party/libxml/src/fuzz/schema.c
new file mode 100644
index 0000000..f1ee938
--- /dev/null
+++ b/third_party/libxml/src/fuzz/schema.c
@@ -0,0 +1,36 @@
+/*
+ * schema.c: a libFuzzer target to test the XML Schema processor.
+ *
+ * See Copyright for the status of this software.
+ */
+
+#include <libxml/xmlschemas.h>
+#include "fuzz.h"
+
+int
+LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
+                     char ***argv ATTRIBUTE_UNUSED) {
+    xmlInitParser();
+    xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
+    xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
+
+    return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(const char *data, size_t size) {
+    xmlSchemaParserCtxtPtr pctxt;
+
+    xmlFuzzDataInit(data, size);
+    xmlFuzzReadEntities();
+
+    pctxt = xmlSchemaNewParserCtxt(xmlFuzzMainUrl());
+    xmlSchemaSetParserErrors(pctxt, xmlFuzzErrorFunc, xmlFuzzErrorFunc, NULL);
+    xmlSchemaFree(xmlSchemaParse(pctxt));
+    xmlSchemaFreeParserCtxt(pctxt);
+
+    xmlFuzzDataCleanup();
+
+    return(0);
+}
+
diff --git a/third_party/libxml/src/fuzz/testFuzzer.c b/third_party/libxml/src/fuzz/testFuzzer.c
new file mode 100644
index 0000000..678f3243
--- /dev/null
+++ b/third_party/libxml/src/fuzz/testFuzzer.c
@@ -0,0 +1,160 @@
+/*
+ * testFuzzer.c: Test program for the custom entity loader used to fuzz
+ * with multiple inputs.
+ *
+ * See Copyright for the status of this software.
+ */
+
+#include <string.h>
+#include <glob.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlstring.h>
+#include "fuzz.h"
+
+#define LLVMFuzzerInitialize fuzzHtmlInit
+#define LLVMFuzzerTestOneInput fuzzHtml
+#include "html.c"
+#undef LLVMFuzzerInitialize
+#undef LLVMFuzzerTestOneInput
+
+#define LLVMFuzzerInitialize fuzzRegexpInit
+#define LLVMFuzzerTestOneInput fuzzRegexp
+#include "regexp.c"
+#undef LLVMFuzzerInitialize
+#undef LLVMFuzzerTestOneInput
+
+#define LLVMFuzzerInitialize fuzzSchemaInit
+#define LLVMFuzzerTestOneInput fuzzSchema
+#include "schema.c"
+#undef LLVMFuzzerInitialize
+#undef LLVMFuzzerTestOneInput
+
+#define LLVMFuzzerInitialize fuzzUriInit
+#define LLVMFuzzerTestOneInput fuzzUri
+#include "uri.c"
+#undef LLVMFuzzerInitialize
+#undef LLVMFuzzerTestOneInput
+
+#define LLVMFuzzerInitialize fuzzXmlInit
+#define LLVMFuzzerTestOneInput fuzzXml
+#include "xml.c"
+#undef LLVMFuzzerInitialize
+#undef LLVMFuzzerTestOneInput
+
+#define LLVMFuzzerInitialize fuzzXPathInit
+#define LLVMFuzzerTestOneInput fuzzXPath
+#include "xpath.c"
+#undef LLVMFuzzerInitialize
+#undef LLVMFuzzerTestOneInput
+
+typedef int
+(*initFunc)(int *argc, char ***argv);
+typedef int
+(*fuzzFunc)(const char *data, size_t size);
+
+int numInputs;
+
+static int
+testFuzzer(initFunc init, fuzzFunc fuzz, const char *pattern) {
+    glob_t globbuf;
+    int ret = -1;
+    int i;
+
+    if (glob(pattern, 0, NULL, &globbuf) != 0) {
+        fprintf(stderr, "pattern %s matches no files\n", pattern);
+        return(-1);
+    }
+
+    if (init != NULL)
+        init(NULL, NULL);
+
+    for (i = 0; i < globbuf.gl_pathc; i++) {
+        const char *path = globbuf.gl_pathv[i];
+        char *data;
+        size_t size;
+
+        data = xmlSlurpFile(path, &size);
+        if (data == NULL) {
+            fprintf(stderr, "couldn't read %s\n", path);
+            goto error;
+        }
+        fuzz(data, size);
+        xmlFree(data);
+
+        numInputs++;
+    }
+
+    ret = 0;
+error:
+    globfree(&globbuf);
+    return(ret);
+}
+
+static int
+testEntityLoader() {
+    static const char data[] =
+        "doc.xml\\\n"
+        "<!DOCTYPE doc SYSTEM \"doc.dtd\">\n"
+        "<doc>&ent;</doc>\\\n"
+        "doc.dtd\\\n"
+        "<!ELEMENT doc (#PCDATA)>\n"
+        "<!ENTITY ent SYSTEM \"ent.txt\">\\\n"
+        "ent.txt\\\n"
+        "Hello, world!\\\n";
+    static xmlChar expected[] =
+        "<?xml version=\"1.0\"?>\n"
+        "<!DOCTYPE doc SYSTEM \"doc.dtd\">\n"
+        "<doc>Hello, world!</doc>\n";
+    const char *docBuffer;
+    size_t docSize;
+    xmlDocPtr doc;
+    xmlChar *out;
+    int ret = 0;
+
+    xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
+
+    xmlFuzzDataInit(data, sizeof(data) - 1);
+    xmlFuzzReadEntities();
+    docBuffer = xmlFuzzMainEntity(&docSize);
+    doc = xmlReadMemory(docBuffer, docSize, NULL, NULL,
+                        XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
+
+    xmlDocDumpMemory(doc, &out, NULL);
+    if (xmlStrcmp(out, expected) != 0) {
+        fprintf(stderr, "Expected:\n%sGot:\n%s", expected, out);
+        ret = 1;
+    }
+
+    xmlFree(out);
+    xmlFreeDoc(doc);
+    xmlFuzzDataCleanup();
+
+    return(ret);
+}
+
+int
+main() {
+    int ret = 0;
+
+    if (testEntityLoader() != 0)
+        ret = 1;
+    if (testFuzzer(fuzzHtmlInit, fuzzHtml, "seed/html/*") != 0)
+        ret = 1;
+    if (testFuzzer(fuzzRegexpInit, fuzzRegexp, "seed/regexp/*") != 0)
+        ret = 1;
+    if (testFuzzer(fuzzSchemaInit, fuzzSchema, "seed/schema/*") != 0)
+        ret = 1;
+    if (testFuzzer(NULL, fuzzUri, "seed/uri/*") != 0)
+        ret = 1;
+    if (testFuzzer(fuzzXmlInit, fuzzXml, "seed/xml/*") != 0)
+        ret = 1;
+    if (testFuzzer(fuzzXPathInit, fuzzXPath, "seed/xpath/*") != 0)
+        ret = 1;
+
+    if (ret == 0)
+        printf("Successfully tested %d inputs\n", numInputs);
+
+    return(ret);
+}
+
diff --git a/third_party/libxml/src/fuzz/uri.c b/third_party/libxml/src/fuzz/uri.c
new file mode 100644
index 0000000..69d0439
--- /dev/null
+++ b/third_party/libxml/src/fuzz/uri.c
@@ -0,0 +1,45 @@
+/*
+ * uri.c: a libFuzzer target to test the URI module.
+ *
+ * See Copyright for the status of this software.
+ */
+
+#include <libxml/uri.h>
+#include "fuzz.h"
+
+int
+LLVMFuzzerTestOneInput(const char *data, size_t size) {
+    xmlURIPtr uri;
+    char *str[2] = { NULL, NULL };
+    size_t numStrings;
+
+    numStrings = xmlFuzzExtractStrings(data, size, str, 2);
+
+    uri = xmlParseURI(str[0]);
+    xmlFree(xmlSaveUri(uri));
+    xmlFreeURI(uri);
+
+    uri = xmlParseURIRaw(str[0], 1);
+    xmlFree(xmlSaveUri(uri));
+    xmlFreeURI(uri);
+
+    xmlFree(xmlURIUnescapeString(str[0], -1, NULL));
+    xmlFree(xmlURIEscape(BAD_CAST str[0]));
+    xmlFree(xmlCanonicPath(BAD_CAST str[0]));
+    xmlFree(xmlPathToURI(BAD_CAST str[0]));
+
+    if (numStrings >= 2) {
+        xmlFree(xmlBuildURI(BAD_CAST str[1], BAD_CAST str[0]));
+        xmlFree(xmlBuildRelativeURI(BAD_CAST str[1], BAD_CAST str[0]));
+        xmlFree(xmlURIEscapeStr(BAD_CAST str[0], BAD_CAST str[1]));
+    }
+
+    /* Modifies string, so must come last. */
+    xmlNormalizeURIPath(str[0]);
+
+    xmlFree(str[0]);
+    xmlFree(str[1]);
+
+    return 0;
+}
+
diff --git a/third_party/libxml/src/fuzz/xml.c b/third_party/libxml/src/fuzz/xml.c
new file mode 100644
index 0000000..09867cf
--- /dev/null
+++ b/third_party/libxml/src/fuzz/xml.c
@@ -0,0 +1,96 @@
+/*
+ * xml.c: a libFuzzer target to test several XML parser interfaces.
+ *
+ * See Copyright for the status of this software.
+ */
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlerror.h>
+#include <libxml/xinclude.h>
+#include <libxml/xmlreader.h>
+#include "fuzz.h"
+
+int
+LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
+                     char ***argv ATTRIBUTE_UNUSED) {
+    xmlInitParser();
+    xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
+    xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
+
+    return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(const char *data, size_t size) {
+    static const size_t maxChunkSize = 128;
+    xmlDocPtr doc;
+    xmlParserCtxtPtr ctxt;
+    xmlTextReaderPtr reader;
+    xmlChar *out;
+    const char *docBuffer, *docUrl;
+    size_t docSize, consumed, chunkSize;
+    int opts, outSize;
+
+    xmlFuzzDataInit(data, size);
+    opts = xmlFuzzReadInt();
+    /* XML_PARSE_HUGE still causes timeouts. */
+    opts &= ~XML_PARSE_HUGE;
+
+    xmlFuzzReadEntities();
+    docBuffer = xmlFuzzMainEntity(&docSize);
+    docUrl = xmlFuzzMainUrl();
+    if (docBuffer == NULL) {
+        xmlFuzzDataCleanup();
+        return(0);
+    }
+
+    /* Pull parser */
+
+    doc = xmlReadMemory(docBuffer, docSize, docUrl, NULL, opts);
+    if (opts & XML_PARSE_XINCLUDE)
+        xmlXIncludeProcessFlags(doc, opts);
+    /* Also test the serializer. */
+    xmlDocDumpMemory(doc, &out, &outSize);
+    xmlFree(out);
+    xmlFreeDoc(doc);
+
+    /* Push parser */
+
+    ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, docUrl);
+    xmlCtxtUseOptions(ctxt, opts);
+
+    for (consumed = 0; consumed < docSize; consumed += chunkSize) {
+        chunkSize = docSize - consumed;
+        if (chunkSize > maxChunkSize)
+            chunkSize = maxChunkSize;
+        xmlParseChunk(ctxt, docBuffer + consumed, chunkSize, 0);
+    }
+
+    xmlParseChunk(ctxt, NULL, 0, 1);
+    if (opts & XML_PARSE_XINCLUDE)
+        xmlXIncludeProcessFlags(ctxt->myDoc, opts);
+    xmlFreeDoc(ctxt->myDoc);
+    xmlFreeParserCtxt(ctxt);
+
+    /* Reader */
+
+    reader = xmlReaderForMemory(docBuffer, docSize, NULL, NULL, opts);
+    while (xmlTextReaderRead(reader) == 1) {
+        if (xmlTextReaderNodeType(reader) == XML_ELEMENT_NODE) {
+            int i, n = xmlTextReaderAttributeCount(reader);
+            for (i=0; i<n; i++) {
+                xmlTextReaderMoveToAttributeNo(reader, i);
+                while (xmlTextReaderReadAttributeValue(reader) == 1);
+            }
+        }
+    }
+    xmlFreeTextReader(reader);
+
+    /* Cleanup */
+
+    xmlFuzzDataCleanup();
+
+    return(0);
+}
+
diff --git a/third_party/libxml/src/fuzz/xpath.c b/third_party/libxml/src/fuzz/xpath.c
new file mode 100644
index 0000000..767acb9
--- /dev/null
+++ b/third_party/libxml/src/fuzz/xpath.c
@@ -0,0 +1,48 @@
+/*
+ * xpath.c: a libFuzzer target to test XPath and XPointer expressions.
+ *
+ * See Copyright for the status of this software.
+ */
+
+#include <libxml/parser.h>
+#include <libxml/xpointer.h>
+#include "fuzz.h"
+
+int
+LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
+                     char ***argv ATTRIBUTE_UNUSED) {
+    xmlInitParser();
+    xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
+
+    return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(const char *data, size_t size) {
+    xmlDocPtr doc;
+    const char *expr, *xml;
+    size_t exprSize, xmlSize;
+
+    xmlFuzzDataInit(data, size);
+
+    expr = xmlFuzzReadString(&exprSize);
+    xml = xmlFuzzReadString(&xmlSize);
+
+    /* Recovery mode allows more input to be fuzzed. */
+    doc = xmlReadMemory(xml, xmlSize, NULL, NULL, XML_PARSE_RECOVER);
+    if (doc != NULL) {
+        xmlXPathContextPtr xpctxt = xmlXPathNewContext(doc);
+
+        /* Operation limit to avoid timeout */
+        xpctxt->opLimit = 500000;
+
+        xmlXPathFreeObject(xmlXPtrEval(BAD_CAST expr, xpctxt));
+        xmlXPathFreeContext(xpctxt);
+    }
+    xmlFreeDoc(doc);
+
+    xmlFuzzDataCleanup();
+
+    return(0);
+}
+
diff --git a/third_party/libxml/src/include/libxml/parser.h b/third_party/libxml/src/include/libxml/parser.h
index 3020b20c..1c86a97 100644
--- a/third_party/libxml/src/include/libxml/parser.h
+++ b/third_party/libxml/src/include/libxml/parser.h
@@ -231,7 +231,7 @@
     int                nameMax;       /* Max depth of the parsing stack */
     const xmlChar *   *nameTab;       /* array of nodes */
 
-    long               nbChars;       /* number of xmlChar processed */
+    long               nbChars;       /* unused */
     long            checkIndex;       /* used by progressive parsing lookup */
     int             keepBlanks;       /* ugly but ... */
     int             disableSAX;       /* SAX callbacks are disabled */
diff --git a/third_party/libxml/src/libxml2.spec b/third_party/libxml/src/libxml2.spec
index d2a5ffb3..6f6c1d0 100644
--- a/third_party/libxml/src/libxml2.spec
+++ b/third_party/libxml/src/libxml2.spec
@@ -204,6 +204,6 @@
 %endif # with_python3
 
 %changelog
-* Fri Apr 10 2020 Daniel Veillard <veillard@redhat.com>
+* Wed Oct  7 2020 Daniel Veillard <veillard@redhat.com>
 - upstream release 2.9.10 see http://xmlsoft.org/news.html
 
diff --git a/third_party/libxml/src/parser.c b/third_party/libxml/src/parser.c
index 87d9e61..5633e3e7 100644
--- a/third_party/libxml/src/parser.c
+++ b/third_party/libxml/src/parser.c
@@ -1074,11 +1074,15 @@
  */
 static void
 xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
+    xmlSAXHandlerPtr sax;
     if (ctxt == NULL) return;
+    sax = ctxt->sax;
 #ifdef LIBXML_SAX1_ENABLED
-    if ((ctxt->sax) &&  (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
-        ((ctxt->sax->startElementNs != NULL) ||
-         (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1;
+    if ((sax) &&  (sax->initialized == XML_SAX2_MAGIC) &&
+        ((sax->startElementNs != NULL) ||
+         (sax->endElementNs != NULL) ||
+         ((sax->startElement == NULL) && (sax->endElement == NULL))))
+        ctxt->sax2 = 1;
 #else
     ctxt->sax2 = 1;
 #endif /* LIBXML_SAX1_ENABLED */
@@ -2051,7 +2055,7 @@
     ((unsigned char *) s)[ 9 ] == c10 )
 
 #define SKIP(val) do {							\
-    ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val);			\
+    ctxt->input->cur += (val),ctxt->input->col+=(val);			\
     if (*ctxt->input->cur == 0)						\
         xmlParserInputGrow(ctxt->input, INPUT_CHUNK);			\
   } while (0)
@@ -2062,7 +2066,6 @@
 	if (*(ctxt->input->cur) == '\n') {				\
 	ctxt->input->line++; ctxt->input->col = 1;			\
 	} else ctxt->input->col++;					\
-	ctxt->nbChars++;						\
 	ctxt->input->cur++;						\
     }									\
     if (*ctxt->input->cur == 0)						\
@@ -2115,7 +2118,6 @@
 #define NEXT1 {								\
 	ctxt->input->col++;						\
 	ctxt->input->cur++;						\
-	ctxt->nbChars++;						\
 	if (*ctxt->input->cur == 0)					\
 	    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);		\
     }
@@ -2152,7 +2154,7 @@
      * It's Okay to use CUR/NEXT here since all the blanks are on
      * the ASCII range.
      */
-    if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) {
+    if (ctxt->instate != XML_PARSER_DTD) {
 	const xmlChar *cur;
 	/*
 	 * if we are in the document content, go really fast
@@ -2328,7 +2330,6 @@
 	if (RAW == ';') {
 	    /* on purpose to avoid reentrancy problems with NEXT and SKIP */
 	    ctxt->input->col++;
-	    ctxt->nbChars ++;
 	    ctxt->input->cur++;
 	}
     } else if  ((RAW == '&') && (NXT(1) == '#')) {
@@ -2357,7 +2358,6 @@
 	if (RAW == ';') {
 	    /* on purpose to avoid reentrancy problems with NEXT and SKIP */
 	    ctxt->input->col++;
-	    ctxt->nbChars ++;
 	    ctxt->input->cur++;
 	}
     } else {
@@ -3329,7 +3329,6 @@
             }
 	    ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
 	    ctxt->input->cur = in;
-	    ctxt->nbChars += count;
 	    ctxt->input->col += count;
 	    if (ret == NULL)
 	        xmlErrMemory(ctxt, NULL);
@@ -3452,7 +3451,6 @@
             }
 	    ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
 	    ctxt->input->cur = in;
-	    ctxt->nbChars += count;
 	    ctxt->input->col += count;
 	    if (ret == NULL) {
 	        xmlErrMemory(ctxt, NULL);
@@ -3489,10 +3487,10 @@
     while (*in != 0 && *in == *cmp) {
 	++in;
 	++cmp;
-	ctxt->input->col++;
     }
     if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
 	/* success */
+	ctxt->input->col += in - ctxt->input->cur;
 	ctxt->input->cur = in;
 	return (const xmlChar*) 1;
     }
@@ -6848,6 +6846,7 @@
 xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
     xmlChar *version;
     const xmlChar *encoding;
+    int oldstate;
 
     /*
      * We know that '<?xml' is here.
@@ -6859,6 +6858,10 @@
 	return;
     }
 
+    /* Avoid expansion of parameter entities when skipping blanks. */
+    oldstate = ctxt->instate;
+    ctxt->instate = XML_PARSER_START;
+
     if (SKIP_BLANKS == 0) {
 	xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 		       "Space needed after '<?xml'\n");
@@ -6886,6 +6889,7 @@
 	/*
 	 * The XML REC instructs us to stop parsing right here
 	 */
+        ctxt->instate = oldstate;
         return;
     }
     if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
@@ -6905,6 +6909,8 @@
 	MOVETO_ENDTAG(CUR_PTR);
 	NEXT;
     }
+
+    ctxt->instate = oldstate;
 }
 
 /**
@@ -8825,6 +8831,7 @@
 	}
 	if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
 	    /* success */
+            ctxt->input->col += in - ctxt->input->cur;
 	    ctxt->input->cur = in;
 	    return((const xmlChar*) 1);
 	}
@@ -12206,12 +12213,12 @@
             }
         }
 	res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
+        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
 	if (res < 0) {
 	    ctxt->errNo = XML_PARSER_EOF;
 	    xmlHaltParser(ctxt);
 	    return (XML_PARSER_EOF);
 	}
-        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
 #ifdef DEBUG_PUSH
 	xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
 #endif
@@ -12226,6 +12233,7 @@
 		size_t current = ctxt->input->cur - ctxt->input->base;
 
 		nbchars = xmlCharEncInput(in, terminate);
+		xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
 		if (nbchars < 0) {
 		    /* TODO 2.6.0 */
 		    xmlGenericError(xmlGenericErrorContext,
@@ -12233,7 +12241,6 @@
                     xmlHaltParser(ctxt);
 		    return(XML_ERR_INVALID_ENCODING);
 		}
-		xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
 	    }
 	}
     }
@@ -13163,7 +13170,7 @@
 
 /**
  * xmlParseBalancedChunkMemory:
- * @doc:  the document the chunk pertains to
+ * @doc:  the document the chunk pertains to (must not be NULL)
  * @sax:  the SAX handler block (possibly NULL)
  * @user_data:  The user data returned on SAX callbacks (possibly NULL)
  * @depth:  Used for loop detection, use 0
@@ -13615,7 +13622,7 @@
 #ifdef LIBXML_SAX1_ENABLED
 /**
  * xmlParseBalancedChunkMemoryRecover:
- * @doc:  the document the chunk pertains to
+ * @doc:  the document the chunk pertains to (must not be NULL)
  * @sax:  the SAX handler block (possibly NULL)
  * @user_data:  The user data returned on SAX callbacks (possibly NULL)
  * @depth:  Used for loop detection, use 0
@@ -13687,6 +13694,7 @@
     } else {
 	xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL);
     }
+    /* doc == NULL is only supported for historic reasons */
     if (doc != NULL) {
 	newDoc->intSubset = doc->intSubset;
 	newDoc->extSubset = doc->extSubset;
@@ -13703,6 +13711,7 @@
     }
     xmlAddChild((xmlNodePtr) newDoc, newRoot);
     nodePush(ctxt, newRoot);
+    /* doc == NULL is only supported for historic reasons */
     if (doc == NULL) {
 	ctxt->myDoc = newDoc;
     } else {
@@ -13772,8 +13781,8 @@
     xmlFreeParserCtxt(ctxt);
     newDoc->intSubset = NULL;
     newDoc->extSubset = NULL;
-    if(doc != NULL)
-	newDoc->oldNs = NULL;
+    /* This leaks the namespace list if doc == NULL */
+    newDoc->oldNs = NULL;
     xmlFreeDoc(newDoc);
 
     return(ret);
@@ -14055,7 +14064,7 @@
 
     if ((ctxt->wellFormed) || recovery) {
         ret = ctxt->myDoc;
-	if (ret != NULL) {
+	if ((ret != NULL) && (ctxt->input->buf != NULL)) {
 	    if (ctxt->input->buf->compressed > 0)
 		ret->compression = 9;
 	    else
@@ -14586,7 +14595,7 @@
     if (xmlParserInitialized != 0)
 	return;
 
-#if defined(WIN32) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
+#if defined(_WIN32) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
 	atexit(xmlCleanupParser);
 #endif
 
@@ -14668,6 +14677,20 @@
     xmlParserInitialized = 0;
 }
 
+#if defined(HAVE_ATTRIBUTE_DESTRUCTOR) && !defined(LIBXML_STATIC) && \
+    !defined(_WIN32)
+static void
+ATTRIBUTE_DESTRUCTOR
+xmlDestructor(void) {
+    /*
+     * Calling custom deallocation functions in a destructor can cause
+     * problems, for example with Nokogiri.
+     */
+    if (xmlFree == free)
+        xmlCleanupParser();
+}
+#endif
+
 /************************************************************************
  *									*
  *	New set (2.6.0) of simpler and more flexible APIs		*
@@ -14756,7 +14779,6 @@
     ctxt->vctxt.warning = xmlParserValidityWarning;
 #endif
     ctxt->record_info = 0;
-    ctxt->nbChars = 0;
     ctxt->checkIndex = 0;
     ctxt->inSubset = 0;
     ctxt->errNo = XML_ERR_OK;
diff --git a/third_party/libxml/src/parserInternals.c b/third_party/libxml/src/parserInternals.c
index 71b899cc..e3828af 100644
--- a/third_party/libxml/src/parserInternals.c
+++ b/third_party/libxml/src/parserInternals.c
@@ -519,8 +519,6 @@
         } else
             /* 1-byte code */
             ctxt->input->cur++;
-
-        ctxt->nbChars++;
     } else {
         /*
          * Assume it's a fixed length encoding (1) with
@@ -533,7 +531,6 @@
         } else
             ctxt->input->col++;
         ctxt->input->cur++;
-        ctxt->nbChars++;
     }
     if (*ctxt->input->cur == 0)
         xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
@@ -677,7 +674,6 @@
 	    }
 	    if (*ctxt->input->cur == 0xD) {
 		if (ctxt->input->cur[1] == 0xA) {
-		    ctxt->nbChars++;
 		    ctxt->input->cur++;
 		}
 		return(0xA);
@@ -693,7 +689,6 @@
     *len = 1;
     if (*ctxt->input->cur == 0xD) {
 	if (ctxt->input->cur[1] == 0xA) {
-	    ctxt->nbChars++;
 	    ctxt->input->cur++;
 	}
 	return(0xA);
@@ -1753,7 +1748,6 @@
         ctxt->options |= XML_PARSE_NOENT;
     }
     ctxt->record_info = 0;
-    ctxt->nbChars = 0;
     ctxt->checkIndex = 0;
     ctxt->inSubset = 0;
     ctxt->errNo = XML_ERR_OK;
diff --git a/third_party/libxml/src/runtest.c b/third_party/libxml/src/runtest.c
index dc5e09a..0f178cb 100644
--- a/third_party/libxml/src/runtest.c
+++ b/third_party/libxml/src/runtest.c
@@ -105,6 +105,7 @@
 };
 
 static int update_results = 0;
+static char* temp_directory = NULL;
 static int checkTestFile(const char *filename);
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
@@ -1699,7 +1700,7 @@
     char *temp;
 
     nb_tests++;
-    temp = resultFilename(filename, "", ".res");
+    temp = resultFilename(filename, temp_directory, ".res");
     if (temp == NULL) {
         fprintf(stderr, "out of memory\n");
         fatalError();
@@ -1818,7 +1819,7 @@
 #endif
     if (doc == NULL)
         return(1);
-    temp = resultFilename(filename, "", ".res");
+    temp = resultFilename(filename, temp_directory, ".res");
     if (temp == NULL) {
         fprintf(stderr, "out of memory\n");
         fatalError();
@@ -2030,7 +2031,7 @@
     doc = xmlReadFile(filename, NULL, options);
     if (doc == NULL)
         return(1);
-    temp = resultFilename(filename, "", ".res");
+    temp = resultFilename(filename, temp_directory, ".res");
     if (temp == NULL) {
         fprintf(stderr, "Out of memory\n");
         fatalError();
@@ -2107,16 +2108,16 @@
 	    xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
 	}
 	res = compareFileMem(result, base, size);
-	if (res != 0) {
-	    fprintf(stderr, "Result for %s failed in %s\n", filename, result);
-	    return(-1);
-	}
     }
     if (doc != NULL) {
 	if (base != NULL)
 	    xmlFree((char *)base);
 	xmlFreeDoc(doc);
     }
+    if (res != 0) {
+        fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+        return(-1);
+    }
     if (err != NULL) {
 	res = compareFileMem(err, testErrors, testErrorsSize);
 	if (res != 0) {
@@ -2177,7 +2178,7 @@
 
     nb_tests++;
     if (result != NULL) {
-	temp = resultFilename(filename, "", ".res");
+	temp = resultFilename(filename, temp_directory, ".res");
 	if (temp == NULL) {
 	    fprintf(stderr, "Out of memory\n");
 	    fatalError();
@@ -2406,7 +2407,7 @@
     int len, ret = 0;
     char *temp;
 
-    temp = resultFilename(filename, "", ".res");
+    temp = resultFilename(filename, temp_directory, ".res");
     if (temp == NULL) {
         fprintf(stderr, "Out of memory\n");
         fatalError();
@@ -2605,7 +2606,7 @@
 	return(-1);
     }
 
-    temp = resultFilename(filename, "", ".res");
+    temp = resultFilename(filename, temp_directory, ".res");
     if (temp == NULL) {
         fprintf(stderr, "Out of memory\n");
         fatalError();
@@ -2703,7 +2704,7 @@
     char str[1024];
     int res = 0, i, ret;
 
-    temp = resultFilename(filename, "", ".res");
+    temp = resultFilename(filename, temp_directory, ".res");
     if (temp == NULL) {
         fprintf(stderr, "Out of memory\n");
         fatalError();
@@ -3007,7 +3008,7 @@
 	return(-1);
     }
 
-    temp = resultFilename(result, "", ".res");
+    temp = resultFilename(result, temp_directory, ".res");
     if (temp == NULL) {
         fprintf(stderr, "Out of memory\n");
         fatalError();
@@ -3178,7 +3179,7 @@
 	return(-1);
     }
 
-    temp = resultFilename(result, "", ".res");
+    temp = resultFilename(result, temp_directory, ".res");
     if (temp == NULL) {
         fprintf(stderr, "Out of memory\n");
         fatalError();
@@ -3528,7 +3529,7 @@
         fprintf(stderr, "Failed to open %s\n", filename);
 	return(-1);
     }
-    temp = resultFilename(filename, "", ".res");
+    temp = resultFilename(filename, temp_directory, ".res");
     if (temp == NULL) {
         fprintf(stderr, "Out of memory\n");
         fatalError();
@@ -4565,6 +4566,8 @@
 	    update_results = 1;
         else if (!strcmp(argv[a], "-quiet"))
 	    tests_quiet = 1;
+        else if (!strcmp(argv[a], "--out"))
+	    temp_directory = argv[++a];
 	else {
 	    for (i = 0; testDescriptions[i].func != NULL; i++) {
 	        if (strstr(testDescriptions[i].desc, argv[a])) {
diff --git a/third_party/libxml/src/win32/Makefile.msvc b/third_party/libxml/src/win32/Makefile.msvc
index f6a0182..725b0ca1 100644
--- a/third_party/libxml/src/win32/Makefile.msvc
+++ b/third_party/libxml/src/win32/Makefile.msvc
@@ -106,6 +106,11 @@
 LDFLAGS = $(LDFLAGS)
 !endif
 
+# append CFLAGS etc. passed on command line
+CPPFLAGS = $(CPPFLAGS) $(EXTRA_CPPFLAGS)
+CFLAGS = $(CFLAGS) $(EXTRA_CFLAGS)
+LDFLAGS = $(LDFLAGS) $(EXTRA_LDFLAGS)
+
 # Libxml object files.
 XML_OBJS = $(XML_INTDIR)\buf.obj\
 	$(XML_INTDIR)\c14n.obj\
diff --git a/third_party/libxml/src/win32/configure.js b/third_party/libxml/src/win32/configure.js
index e2ab31d..cec64c53 100644
--- a/third_party/libxml/src/win32/configure.js
+++ b/third_party/libxml/src/win32/configure.js
@@ -208,15 +208,15 @@
 	while (cf.AtEndOfStream != true) {
 		ln = cf.ReadLine();
 		s = new String(ln);
-		if (s.search(/^LIBXML_MAJOR_VERSION=/) != -1) {
-			vf.WriteLine(s);
-			verMajor = s.substring(s.indexOf("=") + 1, s.length);
-		} else if(s.search(/^LIBXML_MINOR_VERSION=/) != -1) {
-			vf.WriteLine(s);
-			verMinor = s.substring(s.indexOf("=") + 1, s.length);
-		} else if(s.search(/^LIBXML_MICRO_VERSION=/) != -1) {
-			vf.WriteLine(s);
-			verMicro = s.substring(s.indexOf("=") + 1, s.length);
+		if (m = s.match(/^m4_define\(\[MAJOR_VERSION\], (\w+)\)/)) {
+			vf.WriteLine("LIBXML_MAJOR_VERSION=" + m[1]);
+			verMajor = m[1];
+		} else if(m = s.match(/^m4_define\(\[MINOR_VERSION\], (\w+)\)/)) {
+			vf.WriteLine("LIBXML_MINOR_VERSION=" + m[1]);
+			verMinor = m[1];
+		} else if(m = s.match(/^m4_define\(\[MICRO_VERSION\], (\w+)\)/)) {
+			vf.WriteLine("LIBXML_MICRO_VERSION=" + m[1]);
+			verMicro = m[1];
 		} else if(s.search(/^LIBXML_MICRO_VERSION_SUFFIX=/) != -1) {
 			vf.WriteLine(s);
 			verMicroSuffix = s.substring(s.indexOf("=") + 1, s.length);
diff --git a/third_party/libxml/src/xmlIO.c b/third_party/libxml/src/xmlIO.c
index 7827dcf3..57312b9 100644
--- a/third_party/libxml/src/xmlIO.c
+++ b/third_party/libxml/src/xmlIO.c
@@ -3401,18 +3401,12 @@
 		out->error = XML_IO_ENCODER;
 		return(-1);
 	    }
-            if (out->writecallback)
-	        nbchars = xmlBufUse(out->conv);
-            else
-                nbchars = ret;
+            nbchars = ret >= 0 ? ret : 0;
 	} else {
 	    ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
 	    if (ret != 0)
 	        return(-1);
-            if (out->writecallback)
-	        nbchars = xmlBufUse(out->buffer);
-            else
-                nbchars = chunk;
+            nbchars = chunk;
 	}
 	buf += chunk;
 	len -= chunk;
@@ -3599,19 +3593,13 @@
 		out->error = XML_IO_ENCODER;
 		return(-1);
 	    }
-            if (out->writecallback)
-	        nbchars = xmlBufUse(out->conv);
-            else
-                nbchars = ret;
+            nbchars = ret >= 0 ? ret : 0;
 	} else {
 	    ret = escaping(xmlBufEnd(out->buffer), &chunk, str, &cons);
 	    if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
 	        return(-1);
             xmlBufAddLen(out->buffer, chunk);
-            if (out->writecallback)
-	        nbchars = xmlBufUse(out->buffer);
-            else
-                nbchars = chunk;
+            nbchars = chunk;
 	}
 	str += cons;
 	len -= cons;
diff --git a/third_party/libxml/src/xmlreader.c b/third_party/libxml/src/xmlreader.c
index b603c72..01adf74 100644
--- a/third_party/libxml/src/xmlreader.c
+++ b/third_party/libxml/src/xmlreader.c
@@ -48,6 +48,13 @@
 
 #define MAX_ERR_MSG_SIZE 64000
 
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+/* Keeping free objects can hide memory errors. */
+#define MAX_FREE_NODES 1
+#else
+#define MAX_FREE_NODES 100
+#endif
+
 /*
  * The following VA_COPY was coded following an example in
  * the Samba project.  It may not be sufficient for some
@@ -279,6 +286,59 @@
 }
 
 /**
+ * xmlTextReaderWalkRemoveRef:
+ * @data:  Contents of current link
+ * @user:  Value supplied by the user
+ *
+ * Returns 0 to abort the walk or 1 to continue
+ */
+static int
+xmlTextReaderWalkRemoveRef(const void *data, void *user)
+{
+    xmlRefPtr ref = (xmlRefPtr)data;
+    xmlAttrPtr attr = (xmlAttrPtr)user;
+
+    if (ref->attr == attr) { /* Matched: remove and terminate walk */
+        ref->name = xmlStrdup(attr->name);
+        ref->attr = NULL;
+        return 0;
+    }
+    return 1;
+}
+
+/**
+ * xmlTextReaderRemoveRef:
+ * @doc:  the document
+ * @attr:  the attribute
+ *
+ * Remove the given attribute from the Ref table maintained internally.
+ *
+ * Returns -1 if the lookup failed and 0 otherwise
+ */
+static int
+xmlTextReaderRemoveRef(xmlDocPtr doc, xmlAttrPtr attr) {
+    xmlListPtr ref_list;
+    xmlRefTablePtr table;
+    xmlChar *ID;
+
+    if (doc == NULL) return(-1);
+    if (attr == NULL) return(-1);
+    table = (xmlRefTablePtr) doc->refs;
+    if (table == NULL)
+        return(-1);
+
+    ID = xmlNodeListGetString(doc, attr->children, 1);
+    if (ID == NULL)
+        return(-1);
+    ref_list = xmlHashLookup(table, ID);
+    xmlFree(ID);
+    if(ref_list == NULL)
+        return (-1);
+    xmlListWalk(ref_list, xmlTextReaderWalkRemoveRef, attr);
+    return(0);
+}
+
+/**
  * xmlTextReaderFreeProp:
  * @reader:  the xmlTextReaderPtr used
  * @cur:  the node
@@ -299,18 +359,20 @@
 	xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
 
     /* Check for ID removal -> leading to invalid references ! */
-    if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
-	((cur->parent->doc->intSubset != NULL) ||
-	 (cur->parent->doc->extSubset != NULL))) {
+    if ((cur->parent != NULL) && (cur->parent->doc != NULL)) {
         if (xmlIsID(cur->parent->doc, cur->parent, cur))
 	    xmlTextReaderRemoveID(cur->parent->doc, cur);
+	if (((cur->parent->doc->intSubset != NULL) ||
+	     (cur->parent->doc->extSubset != NULL)) &&
+            (xmlIsRef(cur->parent->doc, cur->parent, cur)))
+            xmlTextReaderRemoveRef(cur->parent->doc, cur);
     }
     if (cur->children != NULL)
         xmlTextReaderFreeNodeList(reader, cur->children);
 
     DICT_FREE(cur->name);
     if ((reader != NULL) && (reader->ctxt != NULL) &&
-        (reader->ctxt->freeAttrsNr < 100)) {
+        (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) {
         cur->next = reader->ctxt->freeAttrs;
 	reader->ctxt->freeAttrs = cur;
 	reader->ctxt->freeAttrsNr++;
@@ -411,7 +473,7 @@
 	    if (((cur->type == XML_ELEMENT_NODE) ||
 		 (cur->type == XML_TEXT_NODE)) &&
 	        (reader != NULL) && (reader->ctxt != NULL) &&
-		(reader->ctxt->freeElemsNr < 100)) {
+		(reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
 	        cur->next = reader->ctxt->freeElems;
 		reader->ctxt->freeElems = cur;
 		reader->ctxt->freeElemsNr++;
@@ -499,7 +561,7 @@
     if (((cur->type == XML_ELEMENT_NODE) ||
 	 (cur->type == XML_TEXT_NODE)) &&
 	(reader != NULL) && (reader->ctxt != NULL) &&
-	(reader->ctxt->freeElemsNr < 100)) {
+	(reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
 	cur->next = reader->ctxt->freeElems;
 	reader->ctxt->freeElems = cur;
 	reader->ctxt->freeElemsNr++;
@@ -1436,6 +1498,8 @@
             (reader->node->prev->type != XML_DTD_NODE)) {
 	    xmlNodePtr tmp = reader->node->prev;
 	    if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
+                if (oldnode == tmp)
+                    oldnode = NULL;
 		xmlUnlinkNode(tmp);
 		xmlTextReaderFreeNode(reader, tmp);
 	    }
@@ -2260,6 +2324,7 @@
     if (reader->ctxt != NULL) {
         if (reader->dict == reader->ctxt->dict)
 	    reader->dict = NULL;
+#ifdef LIBXML_VALID_ENABLED
 	if ((reader->ctxt->vctxt.vstateTab != NULL) &&
 	    (reader->ctxt->vctxt.vstateMax > 0)){
 #ifdef LIBXML_REGEXP_ENABLED
@@ -2270,6 +2335,7 @@
 	    reader->ctxt->vctxt.vstateTab = NULL;
 	    reader->ctxt->vctxt.vstateMax = 0;
 	}
+#endif /* LIBXML_VALID_ENABLED */
 	if (reader->ctxt->myDoc != NULL) {
 	    if (reader->preserve == 0)
 		xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
diff --git a/third_party/libxml/src/xmlsave.c b/third_party/libxml/src/xmlsave.c
index 0e698bbd..61a4045 100644
--- a/third_party/libxml/src/xmlsave.c
+++ b/third_party/libxml/src/xmlsave.c
@@ -590,7 +590,6 @@
 static void
 xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
 #endif
-static void xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
 static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
 void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur);
 static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur);
@@ -705,6 +704,7 @@
 static void
 xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
     xmlOutputBufferPtr buf;
+    xmlNodePtr cur;
     int format, level;
 
     if (dtd == NULL) return;
@@ -742,7 +742,9 @@
     level = ctxt->level;
     ctxt->format = 0;
     ctxt->level = -1;
-    xmlNodeListDumpOutput(ctxt, dtd->children);
+    for (cur = dtd->children; cur != NULL; cur = cur->next) {
+        xmlNodeDumpOutputInternal(ctxt, cur);
+    }
     ctxt->format = format;
     ctxt->level = level;
     xmlOutputBufferWrite(buf, 2, "]>");
@@ -776,58 +778,9 @@
     xmlOutputBufferWrite(buf, 1, "\"");
 }
 
-/**
- * xmlAttrListDumpOutput:
- * @buf:  the XML buffer output
- * @doc:  the document
- * @cur:  the first attribute pointer
- * @encoding:  an optional encoding string
- *
- * Dump a list of XML attributes
- */
-static void
-xmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
-    if (cur == NULL) return;
-    while (cur != NULL) {
-        xmlAttrDumpOutput(ctxt, cur);
-	cur = cur->next;
-    }
-}
-
-
-
-/**
- * xmlNodeListDumpOutput:
- * @cur:  the first node
- *
- * Dump an XML node list, recursive behaviour, children are printed too.
- */
-static void
-xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
-    xmlOutputBufferPtr buf;
-
-    if (cur == NULL) return;
-    buf = ctxt->buf;
-    while (cur != NULL) {
-	if ((ctxt->format == 1) && (xmlIndentTreeOutput) &&
-	    ((cur->type == XML_ELEMENT_NODE) ||
-	     (cur->type == XML_COMMENT_NODE) ||
-	     (cur->type == XML_PI_NODE)))
-	    xmlOutputBufferWrite(buf, ctxt->indent_size *
-	                         (ctxt->level > ctxt->indent_nr ?
-				  ctxt->indent_nr : ctxt->level),
-				 ctxt->indent);
-        xmlNodeDumpOutputInternal(ctxt, cur);
-	if (ctxt->format == 1) {
-	    xmlOutputBufferWrite(buf, 1, "\n");
-	}
-	cur = cur->next;
-    }
-}
-
 #ifdef LIBXML_HTML_ENABLED
 /**
- * xmlNodeDumpOutputInternal:
+ * htmlNodeDumpOutputInternal:
  * @cur:  the current node
  *
  * Dump an HTML node, recursive behaviour, children are printed too.
@@ -893,57 +846,111 @@
  */
 static void
 xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
-    int format;
-    xmlNodePtr tmp;
+    int format = ctxt->format;
+    xmlNodePtr tmp, root, unformattedNode = NULL;
+    xmlAttrPtr attr;
     xmlChar *start, *end;
     xmlOutputBufferPtr buf;
 
     if (cur == NULL) return;
     buf = ctxt->buf;
-    if (cur->type == XML_XINCLUDE_START)
-	return;
-    if (cur->type == XML_XINCLUDE_END)
-	return;
-    if ((cur->type == XML_DOCUMENT_NODE) ||
-        (cur->type == XML_HTML_DOCUMENT_NODE)) {
-	xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
-	return;
-    }
-#ifdef LIBXML_HTML_ENABLED
-    if (ctxt->options & XML_SAVE_XHTML) {
-        xhtmlNodeDumpOutput(ctxt, cur);
-        return;
-    }
-    if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) &&
-         (cur->doc->type == XML_HTML_DOCUMENT_NODE) &&
-         ((ctxt->options & XML_SAVE_AS_XML) == 0)) ||
-        (ctxt->options & XML_SAVE_AS_HTML)) {
-	htmlNodeDumpOutputInternal(ctxt, cur);
-	return;
-    }
-#endif
-    if (cur->type == XML_DTD_NODE) {
-        xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
-	return;
-    }
-    if (cur->type == XML_DOCUMENT_FRAG_NODE) {
-        xmlNodeListDumpOutput(ctxt, cur->children);
-	return;
-    }
-    if (cur->type == XML_ELEMENT_DECL) {
-        xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
-	return;
-    }
-    if (cur->type == XML_ATTRIBUTE_DECL) {
-        xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
-	return;
-    }
-    if (cur->type == XML_ENTITY_DECL) {
-        xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
-	return;
-    }
-    if (cur->type == XML_TEXT_NODE) {
-	if (cur->content != NULL) {
+
+    root = cur;
+    while (1) {
+        switch (cur->type) {
+        case XML_DOCUMENT_NODE:
+        case XML_HTML_DOCUMENT_NODE:
+	    xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
+	    break;
+
+        case XML_DTD_NODE:
+            xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
+            break;
+
+        case XML_DOCUMENT_FRAG_NODE:
+            if (cur->children != NULL) {
+                cur = cur->children;
+                continue;
+            }
+	    break;
+
+        case XML_ELEMENT_DECL:
+            xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
+            break;
+
+        case XML_ATTRIBUTE_DECL:
+            xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
+            break;
+
+        case XML_ENTITY_DECL:
+            xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
+            break;
+
+        case XML_ELEMENT_NODE:
+	    if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
+		xmlOutputBufferWrite(buf, ctxt->indent_size *
+				     (ctxt->level > ctxt->indent_nr ?
+				      ctxt->indent_nr : ctxt->level),
+				     ctxt->indent);
+
+            xmlOutputBufferWrite(buf, 1, "<");
+            if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+                xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
+                xmlOutputBufferWrite(buf, 1, ":");
+            }
+            xmlOutputBufferWriteString(buf, (const char *)cur->name);
+            if (cur->nsDef)
+                xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
+            for (attr = cur->properties; attr != NULL; attr = attr->next)
+                xmlAttrDumpOutput(ctxt, attr);
+
+            if (cur->children == NULL) {
+                if ((ctxt->options & XML_SAVE_NO_EMPTY) == 0) {
+                    if (ctxt->format == 2)
+                        xmlOutputBufferWriteWSNonSig(ctxt, 0);
+                    xmlOutputBufferWrite(buf, 2, "/>");
+                } else {
+                    if (ctxt->format == 2)
+                        xmlOutputBufferWriteWSNonSig(ctxt, 1);
+                    xmlOutputBufferWrite(buf, 3, "></");
+                    if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+                        xmlOutputBufferWriteString(buf,
+                                (const char *)cur->ns->prefix);
+                        xmlOutputBufferWrite(buf, 1, ":");
+                    }
+                    xmlOutputBufferWriteString(buf, (const char *)cur->name);
+                    if (ctxt->format == 2)
+                        xmlOutputBufferWriteWSNonSig(ctxt, 0);
+                    xmlOutputBufferWrite(buf, 1, ">");
+                }
+            } else {
+                if (ctxt->format == 1) {
+                    tmp = cur->children;
+                    while (tmp != NULL) {
+                        if ((tmp->type == XML_TEXT_NODE) ||
+                            (tmp->type == XML_CDATA_SECTION_NODE) ||
+                            (tmp->type == XML_ENTITY_REF_NODE)) {
+                            ctxt->format = 0;
+                            unformattedNode = cur;
+                            break;
+                        }
+                        tmp = tmp->next;
+                    }
+                }
+                if (ctxt->format == 2)
+                    xmlOutputBufferWriteWSNonSig(ctxt, 1);
+                xmlOutputBufferWrite(buf, 1, ">");
+                if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
+                if (ctxt->level >= 0) ctxt->level++;
+                cur = cur->children;
+                continue;
+            }
+
+            break;
+
+        case XML_TEXT_NODE:
+	    if (cur->content == NULL)
+                break;
 	    if (cur->name != xmlStringTextNoenc) {
                 xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
 	    } else {
@@ -952,139 +959,140 @@
 		 */
 		xmlOutputBufferWriteString(buf, (const char *) cur->content);
 	    }
-	}
+	    break;
 
-	return;
-    }
-    if (cur->type == XML_PI_NODE) {
-	if (cur->content != NULL) {
-	    xmlOutputBufferWrite(buf, 2, "<?");
-	    xmlOutputBufferWriteString(buf, (const char *)cur->name);
-	    if (cur->content != NULL) {
-	        if (ctxt->format == 2)
-	            xmlOutputBufferWriteWSNonSig(ctxt, 0);
-	        else
-	            xmlOutputBufferWrite(buf, 1, " ");
-		xmlOutputBufferWriteString(buf, (const char *)cur->content);
-	    }
-	    xmlOutputBufferWrite(buf, 2, "?>");
-	} else {
-	    xmlOutputBufferWrite(buf, 2, "<?");
-	    xmlOutputBufferWriteString(buf, (const char *)cur->name);
-	    if (ctxt->format == 2)
-	        xmlOutputBufferWriteWSNonSig(ctxt, 0);
-	    xmlOutputBufferWrite(buf, 2, "?>");
-	}
-	return;
-    }
-    if (cur->type == XML_COMMENT_NODE) {
-	if (cur->content != NULL) {
-	    xmlOutputBufferWrite(buf, 4, "<!--");
-	    xmlOutputBufferWriteString(buf, (const char *)cur->content);
-	    xmlOutputBufferWrite(buf, 3, "-->");
-	}
-	return;
-    }
-    if (cur->type == XML_ENTITY_REF_NODE) {
-        xmlOutputBufferWrite(buf, 1, "&");
-	xmlOutputBufferWriteString(buf, (const char *)cur->name);
-        xmlOutputBufferWrite(buf, 1, ";");
-	return;
-    }
-    if (cur->type == XML_CDATA_SECTION_NODE) {
-	if (cur->content == NULL || *cur->content == '\0') {
-	    xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
-	} else {
-	    start = end = cur->content;
-	    while (*end != '\0') {
-		if ((*end == ']') && (*(end + 1) == ']') &&
-		    (*(end + 2) == '>')) {
-		    end = end + 2;
-		    xmlOutputBufferWrite(buf, 9, "<![CDATA[");
-		    xmlOutputBufferWrite(buf, end - start, (const char *)start);
-		    xmlOutputBufferWrite(buf, 3, "]]>");
-		    start = end;
-		}
-		end++;
-	    }
-	    if (start != end) {
-		xmlOutputBufferWrite(buf, 9, "<![CDATA[");
-		xmlOutputBufferWriteString(buf, (const char *)start);
-		xmlOutputBufferWrite(buf, 3, "]]>");
-	    }
-	}
-	return;
-    }
-    if (cur->type == XML_ATTRIBUTE_NODE) {
-	xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
-	return;
-    }
-    if (cur->type == XML_NAMESPACE_DECL) {
-	xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
-	return;
-    }
+        case XML_PI_NODE:
+	    if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
+		xmlOutputBufferWrite(buf, ctxt->indent_size *
+				     (ctxt->level > ctxt->indent_nr ?
+				      ctxt->indent_nr : ctxt->level),
+				     ctxt->indent);
 
-    format = ctxt->format;
-    if (format == 1) {
-	tmp = cur->children;
-	while (tmp != NULL) {
-	    if ((tmp->type == XML_TEXT_NODE) ||
-		(tmp->type == XML_CDATA_SECTION_NODE) ||
-		(tmp->type == XML_ENTITY_REF_NODE)) {
-		ctxt->format = 0;
-		break;
-	    }
-	    tmp = tmp->next;
-	}
-    }
-    xmlOutputBufferWrite(buf, 1, "<");
-    if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
-        xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
-	xmlOutputBufferWrite(buf, 1, ":");
-    }
+            if (cur->content != NULL) {
+                xmlOutputBufferWrite(buf, 2, "<?");
+                xmlOutputBufferWriteString(buf, (const char *)cur->name);
+                if (cur->content != NULL) {
+                    if (ctxt->format == 2)
+                        xmlOutputBufferWriteWSNonSig(ctxt, 0);
+                    else
+                        xmlOutputBufferWrite(buf, 1, " ");
+                    xmlOutputBufferWriteString(buf,
+                            (const char *)cur->content);
+                }
+                xmlOutputBufferWrite(buf, 2, "?>");
+            } else {
+                xmlOutputBufferWrite(buf, 2, "<?");
+                xmlOutputBufferWriteString(buf, (const char *)cur->name);
+                if (ctxt->format == 2)
+                    xmlOutputBufferWriteWSNonSig(ctxt, 0);
+                xmlOutputBufferWrite(buf, 2, "?>");
+            }
+            break;
 
-    xmlOutputBufferWriteString(buf, (const char *)cur->name);
-    if (cur->nsDef)
-        xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
-    if (cur->properties != NULL)
-        xmlAttrListDumpOutput(ctxt, cur->properties);
+        case XML_COMMENT_NODE:
+	    if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
+		xmlOutputBufferWrite(buf, ctxt->indent_size *
+				     (ctxt->level > ctxt->indent_nr ?
+				      ctxt->indent_nr : ctxt->level),
+				     ctxt->indent);
 
-    if (((cur->type == XML_ELEMENT_NODE) || (cur->content == NULL)) &&
-	(cur->children == NULL) && ((ctxt->options & XML_SAVE_NO_EMPTY) == 0)) {
-        if (ctxt->format == 2)
-            xmlOutputBufferWriteWSNonSig(ctxt, 0);
-        xmlOutputBufferWrite(buf, 2, "/>");
-	ctxt->format = format;
-	return;
-    }
-    if (ctxt->format == 2)
-        xmlOutputBufferWriteWSNonSig(ctxt, 1);
-    xmlOutputBufferWrite(buf, 1, ">");
-    if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
-	xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
-    }
-    if (cur->children != NULL) {
-	if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
-	if (ctxt->level >= 0) ctxt->level++;
-	xmlNodeListDumpOutput(ctxt, cur->children);
-	if (ctxt->level > 0) ctxt->level--;
-	if ((xmlIndentTreeOutput) && (ctxt->format == 1))
-	    xmlOutputBufferWrite(buf, ctxt->indent_size *
-	                         (ctxt->level > ctxt->indent_nr ?
-				  ctxt->indent_nr : ctxt->level),
-				 ctxt->indent);
-    }
-    xmlOutputBufferWrite(buf, 2, "</");
-    if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
-        xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
-	xmlOutputBufferWrite(buf, 1, ":");
-    }
+            if (cur->content != NULL) {
+                xmlOutputBufferWrite(buf, 4, "<!--");
+                xmlOutputBufferWriteString(buf, (const char *)cur->content);
+                xmlOutputBufferWrite(buf, 3, "-->");
+            }
+            break;
 
-    xmlOutputBufferWriteString(buf, (const char *)cur->name);
-    if (ctxt->format == 2)
-        xmlOutputBufferWriteWSNonSig(ctxt, 0);
-    xmlOutputBufferWrite(buf, 1, ">");
-    ctxt->format = format;
+        case XML_ENTITY_REF_NODE:
+            xmlOutputBufferWrite(buf, 1, "&");
+            xmlOutputBufferWriteString(buf, (const char *)cur->name);
+            xmlOutputBufferWrite(buf, 1, ";");
+            break;
+
+        case XML_CDATA_SECTION_NODE:
+            if (cur->content == NULL || *cur->content == '\0') {
+                xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
+            } else {
+                start = end = cur->content;
+                while (*end != '\0') {
+                    if ((*end == ']') && (*(end + 1) == ']') &&
+                        (*(end + 2) == '>')) {
+                        end = end + 2;
+                        xmlOutputBufferWrite(buf, 9, "<![CDATA[");
+                        xmlOutputBufferWrite(buf, end - start,
+                                (const char *)start);
+                        xmlOutputBufferWrite(buf, 3, "]]>");
+                        start = end;
+                    }
+                    end++;
+                }
+                if (start != end) {
+                    xmlOutputBufferWrite(buf, 9, "<![CDATA[");
+                    xmlOutputBufferWriteString(buf, (const char *)start);
+                    xmlOutputBufferWrite(buf, 3, "]]>");
+                }
+            }
+            break;
+
+        case XML_ATTRIBUTE_NODE:
+            xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
+            break;
+
+        case XML_NAMESPACE_DECL:
+            xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
+            break;
+
+        default:
+            break;
+        }
+
+        while (1) {
+            if (cur == root)
+                return;
+            if ((ctxt->format == 1) &&
+                (cur->type != XML_XINCLUDE_START) &&
+                (cur->type != XML_XINCLUDE_END))
+                xmlOutputBufferWrite(buf, 1, "\n");
+            if (cur->next != NULL) {
+                cur = cur->next;
+                break;
+            }
+
+            /*
+             * The parent should never be NULL here but we want to handle
+             * corrupted documents gracefully.
+             */
+            if (cur->parent == NULL)
+                return;
+            cur = cur->parent;
+
+            if (cur->type == XML_ELEMENT_NODE) {
+                if (ctxt->level > 0) ctxt->level--;
+                if ((xmlIndentTreeOutput) && (ctxt->format == 1))
+                    xmlOutputBufferWrite(buf, ctxt->indent_size *
+                                         (ctxt->level > ctxt->indent_nr ?
+                                          ctxt->indent_nr : ctxt->level),
+                                         ctxt->indent);
+
+                xmlOutputBufferWrite(buf, 2, "</");
+                if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+                    xmlOutputBufferWriteString(buf,
+                            (const char *)cur->ns->prefix);
+                    xmlOutputBufferWrite(buf, 1, ":");
+                }
+
+                xmlOutputBufferWriteString(buf, (const char *)cur->name);
+                if (ctxt->format == 2)
+                    xmlOutputBufferWriteWSNonSig(ctxt, 0);
+                xmlOutputBufferWrite(buf, 1, ">");
+
+                if (cur == unformattedNode) {
+                    ctxt->format = format;
+                    unformattedNode = NULL;
+                }
+            }
+        }
+    }
 }
 
 /**
@@ -1224,7 +1232,9 @@
 		else
 #endif
 		    xmlNodeDumpOutputInternal(ctxt, child);
-		xmlOutputBufferWrite(buf, 1, "\n");
+                if ((child->type != XML_XINCLUDE_START) &&
+                    (child->type != XML_XINCLUDE_END))
+                    xmlOutputBufferWrite(buf, 1, "\n");
 		child = child->next;
 	    }
 	}
@@ -1396,40 +1406,6 @@
 }
 
 /**
- * xhtmlNodeListDumpOutput:
- * @buf:  the XML buffer output
- * @doc:  the XHTML document
- * @cur:  the first node
- * @level: the imbrication level for indenting
- * @format: is formatting allowed
- * @encoding:  an optional encoding string
- *
- * Dump an XML node list, recursive behaviour, children are printed too.
- * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
- * or xmlKeepBlanksDefault(0) was called
- */
-static void
-xhtmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
-    xmlOutputBufferPtr buf;
-
-    if (cur == NULL) return;
-    buf = ctxt->buf;
-    while (cur != NULL) {
-	if ((ctxt->format == 1) && (xmlIndentTreeOutput) &&
-	    (cur->type == XML_ELEMENT_NODE))
-	    xmlOutputBufferWrite(buf, ctxt->indent_size *
-	                         (ctxt->level > ctxt->indent_nr ?
-				  ctxt->indent_nr : ctxt->level),
-				 ctxt->indent);
-        xhtmlNodeDumpOutput(ctxt, cur);
-	if (ctxt->format == 1) {
-	    xmlOutputBufferWrite(buf, 1, "\n");
-	}
-	cur = cur->next;
-    }
-}
-
-/**
  * xhtmlNodeDumpOutput:
  * @buf:  the XML buffer output
  * @doc:  the XHTML document
@@ -1442,48 +1418,195 @@
  */
 static void
 xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
-    int format, addmeta = 0;
-    xmlNodePtr tmp;
+    int format = ctxt->format, addmeta;
+    xmlNodePtr tmp, root, unformattedNode = NULL;
     xmlChar *start, *end;
-    xmlOutputBufferPtr buf;
+    xmlOutputBufferPtr buf = ctxt->buf;
 
     if (cur == NULL) return;
-    if ((cur->type == XML_DOCUMENT_NODE) ||
-        (cur->type == XML_HTML_DOCUMENT_NODE)) {
-        xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
-	return;
-    }
-    if (cur->type == XML_XINCLUDE_START)
-	return;
-    if (cur->type == XML_XINCLUDE_END)
-	return;
-    if (cur->type == XML_NAMESPACE_DECL) {
-	xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
-	return;
-    }
-    if (cur->type == XML_DTD_NODE) {
-        xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
-	return;
-    }
-    if (cur->type == XML_DOCUMENT_FRAG_NODE) {
-        xhtmlNodeListDumpOutput(ctxt, cur->children);
-	return;
-    }
-    buf = ctxt->buf;
-    if (cur->type == XML_ELEMENT_DECL) {
-        xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
-	return;
-    }
-    if (cur->type == XML_ATTRIBUTE_DECL) {
-        xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
-	return;
-    }
-    if (cur->type == XML_ENTITY_DECL) {
-        xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
-	return;
-    }
-    if (cur->type == XML_TEXT_NODE) {
-	if (cur->content != NULL) {
+
+    root = cur;
+    while (1) {
+        switch (cur->type) {
+        case XML_DOCUMENT_NODE:
+        case XML_HTML_DOCUMENT_NODE:
+            xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
+	    break;
+
+        case XML_NAMESPACE_DECL:
+	    xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
+	    break;
+
+        case XML_DTD_NODE:
+            xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
+	    break;
+
+        case XML_DOCUMENT_FRAG_NODE:
+            if (cur->children) {
+                cur = cur->children;
+                continue;
+            }
+            break;
+
+        case XML_ELEMENT_DECL:
+            xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
+	    break;
+
+        case XML_ATTRIBUTE_DECL:
+            xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
+	    break;
+
+        case XML_ENTITY_DECL:
+            xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
+	    break;
+
+        case XML_ELEMENT_NODE:
+            addmeta = 0;
+
+	    if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
+		xmlOutputBufferWrite(buf, ctxt->indent_size *
+				     (ctxt->level > ctxt->indent_nr ?
+				      ctxt->indent_nr : ctxt->level),
+				     ctxt->indent);
+
+            xmlOutputBufferWrite(buf, 1, "<");
+            if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+                xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
+                xmlOutputBufferWrite(buf, 1, ":");
+            }
+
+            xmlOutputBufferWriteString(buf, (const char *)cur->name);
+            if (cur->nsDef)
+                xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
+            if ((xmlStrEqual(cur->name, BAD_CAST "html") &&
+                (cur->ns == NULL) && (cur->nsDef == NULL))) {
+                /*
+                 * 3.1.1. Strictly Conforming Documents A.3.1.1 3/
+                 */
+                xmlOutputBufferWriteString(buf,
+                        " xmlns=\"http://www.w3.org/1999/xhtml\"");
+            }
+            if (cur->properties != NULL)
+                xhtmlAttrListDumpOutput(ctxt, cur->properties);
+
+            if ((cur->parent != NULL) &&
+                (cur->parent->parent == (xmlNodePtr) cur->doc) &&
+                xmlStrEqual(cur->name, BAD_CAST"head") &&
+                xmlStrEqual(cur->parent->name, BAD_CAST"html")) {
+
+                tmp = cur->children;
+                while (tmp != NULL) {
+                    if (xmlStrEqual(tmp->name, BAD_CAST"meta")) {
+                        xmlChar *httpequiv;
+
+                        httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv");
+                        if (httpequiv != NULL) {
+                            if (xmlStrcasecmp(httpequiv,
+                                        BAD_CAST"Content-Type") == 0) {
+                                xmlFree(httpequiv);
+                                break;
+                            }
+                            xmlFree(httpequiv);
+                        }
+                    }
+                    tmp = tmp->next;
+                }
+                if (tmp == NULL)
+                    addmeta = 1;
+            }
+
+            if (cur->children == NULL) {
+                if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) &&
+                    ((xhtmlIsEmpty(cur) == 1) && (addmeta == 0))) {
+                    /*
+                     * C.2. Empty Elements
+                     */
+                    xmlOutputBufferWrite(buf, 3, " />");
+                } else {
+                    if (addmeta == 1) {
+                        xmlOutputBufferWrite(buf, 1, ">");
+                        if (ctxt->format == 1) {
+                            xmlOutputBufferWrite(buf, 1, "\n");
+                            if (xmlIndentTreeOutput)
+                                xmlOutputBufferWrite(buf, ctxt->indent_size *
+                                    (ctxt->level + 1 > ctxt->indent_nr ?
+                                    ctxt->indent_nr : ctxt->level + 1),
+                                    ctxt->indent);
+                        }
+                        xmlOutputBufferWriteString(buf,
+                                "<meta http-equiv=\"Content-Type\" "
+                                "content=\"text/html; charset=");
+                        if (ctxt->encoding) {
+                            xmlOutputBufferWriteString(buf,
+                                    (const char *)ctxt->encoding);
+                        } else {
+                            xmlOutputBufferWrite(buf, 5, "UTF-8");
+                        }
+                        xmlOutputBufferWrite(buf, 4, "\" />");
+                        if (ctxt->format == 1)
+                            xmlOutputBufferWrite(buf, 1, "\n");
+                    } else {
+                        xmlOutputBufferWrite(buf, 1, ">");
+                    }
+                    /*
+                     * C.3. Element Minimization and Empty Element Content
+                     */
+                    xmlOutputBufferWrite(buf, 2, "</");
+                    if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+                        xmlOutputBufferWriteString(buf,
+                                (const char *)cur->ns->prefix);
+                        xmlOutputBufferWrite(buf, 1, ":");
+                    }
+                    xmlOutputBufferWriteString(buf, (const char *)cur->name);
+                    xmlOutputBufferWrite(buf, 1, ">");
+                }
+            } else {
+                xmlOutputBufferWrite(buf, 1, ">");
+                if (addmeta == 1) {
+                    if (ctxt->format == 1) {
+                        xmlOutputBufferWrite(buf, 1, "\n");
+                        if (xmlIndentTreeOutput)
+                            xmlOutputBufferWrite(buf, ctxt->indent_size *
+                                (ctxt->level + 1 > ctxt->indent_nr ?
+                                ctxt->indent_nr : ctxt->level + 1),
+                                ctxt->indent);
+                    }
+                    xmlOutputBufferWriteString(buf,
+                            "<meta http-equiv=\"Content-Type\" "
+                            "content=\"text/html; charset=");
+                    if (ctxt->encoding) {
+                        xmlOutputBufferWriteString(buf,
+                                (const char *)ctxt->encoding);
+                    } else {
+                        xmlOutputBufferWrite(buf, 5, "UTF-8");
+                    }
+                    xmlOutputBufferWrite(buf, 4, "\" />");
+                }
+
+                if (ctxt->format == 1) {
+                    tmp = cur->children;
+                    while (tmp != NULL) {
+                        if ((tmp->type == XML_TEXT_NODE) ||
+                            (tmp->type == XML_ENTITY_REF_NODE)) {
+                            unformattedNode = cur;
+                            ctxt->format = 0;
+                            break;
+                        }
+                        tmp = tmp->next;
+                    }
+                }
+
+                if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
+                if (ctxt->level >= 0) ctxt->level++;
+                cur = cur->children;
+                continue;
+            }
+
+            break;
+
+        case XML_TEXT_NODE:
+	    if (cur->content == NULL)
+                break;
 	    if ((cur->name == xmlStringText) ||
 		(cur->name != xmlStringTextNoenc)) {
                 xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
@@ -1493,286 +1616,115 @@
 		 */
 		xmlOutputBufferWriteString(buf, (const char *) cur->content);
 	    }
-	}
+	    break;
 
-	return;
-    }
-    if (cur->type == XML_PI_NODE) {
-	if (cur->content != NULL) {
-	    xmlOutputBufferWrite(buf, 2, "<?");
-	    xmlOutputBufferWriteString(buf, (const char *)cur->name);
-	    if (cur->content != NULL) {
-		xmlOutputBufferWrite(buf, 1, " ");
-		xmlOutputBufferWriteString(buf, (const char *)cur->content);
-	    }
-	    xmlOutputBufferWrite(buf, 2, "?>");
-	} else {
-	    xmlOutputBufferWrite(buf, 2, "<?");
-	    xmlOutputBufferWriteString(buf, (const char *)cur->name);
-	    xmlOutputBufferWrite(buf, 2, "?>");
-	}
-	return;
-    }
-    if (cur->type == XML_COMMENT_NODE) {
-	if (cur->content != NULL) {
-	    xmlOutputBufferWrite(buf, 4, "<!--");
-	    xmlOutputBufferWriteString(buf, (const char *)cur->content);
-	    xmlOutputBufferWrite(buf, 3, "-->");
-	}
-	return;
-    }
-    if (cur->type == XML_ENTITY_REF_NODE) {
-        xmlOutputBufferWrite(buf, 1, "&");
-	xmlOutputBufferWriteString(buf, (const char *)cur->name);
-        xmlOutputBufferWrite(buf, 1, ";");
-	return;
-    }
-    if (cur->type == XML_CDATA_SECTION_NODE) {
-	if (cur->content == NULL || *cur->content == '\0') {
-	    xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
-	} else {
-	    start = end = cur->content;
-	    while (*end != '\0') {
-		if (*end == ']' && *(end + 1) == ']' && *(end + 2) == '>') {
-		    end = end + 2;
-		    xmlOutputBufferWrite(buf, 9, "<![CDATA[");
-		    xmlOutputBufferWrite(buf, end - start, (const char *)start);
-		    xmlOutputBufferWrite(buf, 3, "]]>");
-		    start = end;
-		}
-		end++;
-	    }
-	    if (start != end) {
-		xmlOutputBufferWrite(buf, 9, "<![CDATA[");
-		xmlOutputBufferWriteString(buf, (const char *)start);
-		xmlOutputBufferWrite(buf, 3, "]]>");
-	    }
-	}
-	return;
-    }
-    if (cur->type == XML_ATTRIBUTE_NODE) {
-        xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
-	return;
-    }
+        case XML_PI_NODE:
+            if (cur->content != NULL) {
+                xmlOutputBufferWrite(buf, 2, "<?");
+                xmlOutputBufferWriteString(buf, (const char *)cur->name);
+                if (cur->content != NULL) {
+                    xmlOutputBufferWrite(buf, 1, " ");
+                    xmlOutputBufferWriteString(buf,
+                            (const char *)cur->content);
+                }
+                xmlOutputBufferWrite(buf, 2, "?>");
+            } else {
+                xmlOutputBufferWrite(buf, 2, "<?");
+                xmlOutputBufferWriteString(buf, (const char *)cur->name);
+                xmlOutputBufferWrite(buf, 2, "?>");
+            }
+            break;
 
-    format = ctxt->format;
-    if (format == 1) {
-	tmp = cur->children;
-	while (tmp != NULL) {
-	    if ((tmp->type == XML_TEXT_NODE) ||
-		(tmp->type == XML_ENTITY_REF_NODE)) {
-		format = 0;
-		break;
-	    }
-	    tmp = tmp->next;
-	}
-    }
-    xmlOutputBufferWrite(buf, 1, "<");
-    if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
-        xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
-	xmlOutputBufferWrite(buf, 1, ":");
-    }
+        case XML_COMMENT_NODE:
+            if (cur->content != NULL) {
+                xmlOutputBufferWrite(buf, 4, "<!--");
+                xmlOutputBufferWriteString(buf, (const char *)cur->content);
+                xmlOutputBufferWrite(buf, 3, "-->");
+            }
+            break;
 
-    xmlOutputBufferWriteString(buf, (const char *)cur->name);
-    if (cur->nsDef)
-        xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
-    if ((xmlStrEqual(cur->name, BAD_CAST "html") &&
-	(cur->ns == NULL) && (cur->nsDef == NULL))) {
-	/*
-	 * 3.1.1. Strictly Conforming Documents A.3.1.1 3/
-	 */
-	xmlOutputBufferWriteString(buf,
-		" xmlns=\"http://www.w3.org/1999/xhtml\"");
-    }
-    if (cur->properties != NULL)
-        xhtmlAttrListDumpOutput(ctxt, cur->properties);
+        case XML_ENTITY_REF_NODE:
+            xmlOutputBufferWrite(buf, 1, "&");
+            xmlOutputBufferWriteString(buf, (const char *)cur->name);
+            xmlOutputBufferWrite(buf, 1, ";");
+            break;
 
-    if ((cur->type == XML_ELEMENT_NODE) &&
-        (cur->parent != NULL) &&
-        (cur->parent->parent == (xmlNodePtr) cur->doc) &&
-        xmlStrEqual(cur->name, BAD_CAST"head") &&
-        xmlStrEqual(cur->parent->name, BAD_CAST"html")) {
-
-        tmp = cur->children;
-        while (tmp != NULL) {
-            if (xmlStrEqual(tmp->name, BAD_CAST"meta")) {
-                xmlChar *httpequiv;
-
-                httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv");
-                if (httpequiv != NULL) {
-                    if (xmlStrcasecmp(httpequiv, BAD_CAST"Content-Type") == 0) {
-                        xmlFree(httpequiv);
-                        break;
+        case XML_CDATA_SECTION_NODE:
+            if (cur->content == NULL || *cur->content == '\0') {
+                xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
+            } else {
+                start = end = cur->content;
+                while (*end != '\0') {
+                    if (*end == ']' && *(end + 1) == ']' &&
+                        *(end + 2) == '>') {
+                        end = end + 2;
+                        xmlOutputBufferWrite(buf, 9, "<![CDATA[");
+                        xmlOutputBufferWrite(buf, end - start,
+                                (const char *)start);
+                        xmlOutputBufferWrite(buf, 3, "]]>");
+                        start = end;
                     }
-                    xmlFree(httpequiv);
+                    end++;
+                }
+                if (start != end) {
+                    xmlOutputBufferWrite(buf, 9, "<![CDATA[");
+                    xmlOutputBufferWriteString(buf, (const char *)start);
+                    xmlOutputBufferWrite(buf, 3, "]]>");
                 }
             }
-            tmp = tmp->next;
+            break;
+
+        case XML_ATTRIBUTE_NODE:
+            xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
+	    break;
+
+        default:
+            break;
         }
-        if (tmp == NULL)
-            addmeta = 1;
+
+        while (1) {
+            if (cur == root)
+                return;
+            if (ctxt->format == 1)
+                xmlOutputBufferWrite(buf, 1, "\n");
+            if (cur->next != NULL) {
+                cur = cur->next;
+                break;
+            }
+
+            /*
+             * The parent should never be NULL here but we want to handle
+             * corrupted documents gracefully.
+             */
+            if (cur->parent == NULL)
+                return;
+            cur = cur->parent;
+
+            if (cur->type == XML_ELEMENT_NODE) {
+                if (ctxt->level > 0) ctxt->level--;
+                if ((xmlIndentTreeOutput) && (ctxt->format == 1))
+                    xmlOutputBufferWrite(buf, ctxt->indent_size *
+                                         (ctxt->level > ctxt->indent_nr ?
+                                          ctxt->indent_nr : ctxt->level),
+                                         ctxt->indent);
+
+                xmlOutputBufferWrite(buf, 2, "</");
+                if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+                    xmlOutputBufferWriteString(buf,
+                            (const char *)cur->ns->prefix);
+                    xmlOutputBufferWrite(buf, 1, ":");
+                }
+
+                xmlOutputBufferWriteString(buf, (const char *)cur->name);
+                xmlOutputBufferWrite(buf, 1, ">");
+
+                if (cur == unformattedNode) {
+                    ctxt->format = format;
+                    unformattedNode = NULL;
+                }
+            }
+        }
     }
-
-    if ((cur->type == XML_ELEMENT_NODE) && (cur->children == NULL)) {
-	if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) &&
-	    ((xhtmlIsEmpty(cur) == 1) && (addmeta == 0))) {
-	    /*
-	     * C.2. Empty Elements
-	     */
-	    xmlOutputBufferWrite(buf, 3, " />");
-	} else {
-		if (addmeta == 1) {
-			xmlOutputBufferWrite(buf, 1, ">");
-			if (ctxt->format == 1) {
-				xmlOutputBufferWrite(buf, 1, "\n");
-				if (xmlIndentTreeOutput)
-					xmlOutputBufferWrite(buf, ctxt->indent_size *
-					(ctxt->level + 1 > ctxt->indent_nr ?
-					ctxt->indent_nr : ctxt->level + 1), ctxt->indent);
-			}
-			xmlOutputBufferWriteString(buf,
-				"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
-			if (ctxt->encoding) {
-				xmlOutputBufferWriteString(buf, (const char *)ctxt->encoding);
-			} else {
-				xmlOutputBufferWrite(buf, 5, "UTF-8");
-			}
-			xmlOutputBufferWrite(buf, 4, "\" />");
-			if (ctxt->format == 1)
-				xmlOutputBufferWrite(buf, 1, "\n");
-		} else {
-			xmlOutputBufferWrite(buf, 1, ">");
-		}
-	    /*
-	     * C.3. Element Minimization and Empty Element Content
-	     */
-	    xmlOutputBufferWrite(buf, 2, "</");
-	    if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
-		xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
-		xmlOutputBufferWrite(buf, 1, ":");
-	    }
-	    xmlOutputBufferWriteString(buf, (const char *)cur->name);
-	    xmlOutputBufferWrite(buf, 1, ">");
-	}
-	return;
-    }
-    xmlOutputBufferWrite(buf, 1, ">");
-	if (addmeta == 1) {
-		if (ctxt->format == 1) {
-			xmlOutputBufferWrite(buf, 1, "\n");
-			if (xmlIndentTreeOutput)
-				xmlOutputBufferWrite(buf, ctxt->indent_size *
-				(ctxt->level + 1 > ctxt->indent_nr ?
-				ctxt->indent_nr : ctxt->level + 1), ctxt->indent);
-		}
-		xmlOutputBufferWriteString(buf,
-			"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
-		if (ctxt->encoding) {
-			xmlOutputBufferWriteString(buf, (const char *)ctxt->encoding);
-		} else {
-			xmlOutputBufferWrite(buf, 5, "UTF-8");
-		}
-		xmlOutputBufferWrite(buf, 4, "\" />");
-	}
-    if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
-	xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
-    }
-
-#if 0
-    /*
-    * This was removed due to problems with HTML processors.
-    * See bug #345147.
-    */
-    /*
-     * 4.8. Script and Style elements
-     */
-    if ((cur->type == XML_ELEMENT_NODE) &&
-	((xmlStrEqual(cur->name, BAD_CAST "script")) ||
-	 (xmlStrEqual(cur->name, BAD_CAST "style"))) &&
-	((cur->ns == NULL) ||
-	 (xmlStrEqual(cur->ns->href, XHTML_NS_NAME)))) {
-	xmlNodePtr child = cur->children;
-
-	while (child != NULL) {
-	    if (child->type == XML_TEXT_NODE) {
-		if ((xmlStrchr(child->content, '<') == NULL) &&
-		    (xmlStrchr(child->content, '&') == NULL) &&
-		    (xmlStrstr(child->content, BAD_CAST "]]>") == NULL)) {
-		    /* Nothing to escape, so just output as is... */
-		    /* FIXME: Should we do something about "--" also? */
-		    int level = ctxt->level;
-		    int indent = ctxt->format;
-
-		    ctxt->level = 0;
-		    ctxt->format = 0;
-		    xmlOutputBufferWriteString(buf, (const char *) child->content);
-		    /* (We cannot use xhtmlNodeDumpOutput() here because
-		     * we wish to leave '>' unescaped!) */
-		    ctxt->level = level;
-		    ctxt->format = indent;
-		} else {
-		    /* We must use a CDATA section.  Unfortunately,
-		     * this will break CSS and JavaScript when read by
-		     * a browser in HTML4-compliant mode. :-( */
-		    start = end = child->content;
-		    while (*end != '\0') {
-			if (*end == ']' &&
-			    *(end + 1) == ']' &&
-			    *(end + 2) == '>') {
-			    end = end + 2;
-			    xmlOutputBufferWrite(buf, 9, "<![CDATA[");
-			    xmlOutputBufferWrite(buf, end - start,
-						 (const char *)start);
-			    xmlOutputBufferWrite(buf, 3, "]]>");
-			    start = end;
-			}
-			end++;
-		    }
-		    if (start != end) {
-			xmlOutputBufferWrite(buf, 9, "<![CDATA[");
-			xmlOutputBufferWrite(buf, end - start,
-			                     (const char *)start);
-			xmlOutputBufferWrite(buf, 3, "]]>");
-		    }
-		}
-	    } else {
-		int level = ctxt->level;
-		int indent = ctxt->format;
-
-		ctxt->level = 0;
-		ctxt->format = 0;
-		xhtmlNodeDumpOutput(ctxt, child);
-		ctxt->level = level;
-		ctxt->format = indent;
-	    }
-	    child = child->next;
-	}
-    }
-#endif
-
-    if (cur->children != NULL) {
-	int indent = ctxt->format;
-
-	if (format == 1) xmlOutputBufferWrite(buf, 1, "\n");
-	if (ctxt->level >= 0) ctxt->level++;
-	ctxt->format = format;
-	xhtmlNodeListDumpOutput(ctxt, cur->children);
-	if (ctxt->level > 0) ctxt->level--;
-	ctxt->format = indent;
-	if ((xmlIndentTreeOutput) && (format == 1))
-	    xmlOutputBufferWrite(buf, ctxt->indent_size *
-	                         (ctxt->level > ctxt->indent_nr ?
-				  ctxt->indent_nr : ctxt->level),
-				 ctxt->indent);
-    }
-    xmlOutputBufferWrite(buf, 2, "</");
-    if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
-        xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
-	xmlOutputBufferWrite(buf, 1, ":");
-    }
-
-    xmlOutputBufferWriteString(buf, (const char *)cur->name);
-    xmlOutputBufferWrite(buf, 1, ">");
 }
 #endif
 
@@ -1932,12 +1884,25 @@
  * Returns the number of byte written or -1 in case of error
  */
 long
-xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr node)
+xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr cur)
 {
     long ret = 0;
 
-    if ((ctxt == NULL) || (node == NULL)) return(-1);
-    xmlNodeDumpOutputInternal(ctxt, node);
+    if ((ctxt == NULL) || (cur == NULL)) return(-1);
+#ifdef LIBXML_HTML_ENABLED
+    if (ctxt->options & XML_SAVE_XHTML) {
+        xhtmlNodeDumpOutput(ctxt, cur);
+        return(ret);
+    }
+    if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) &&
+         (cur->doc->type == XML_HTML_DOCUMENT_NODE) &&
+         ((ctxt->options & XML_SAVE_AS_XML) == 0)) ||
+        (ctxt->options & XML_SAVE_AS_HTML)) {
+	htmlNodeDumpOutputInternal(ctxt, cur);
+	return(ret);
+    }
+#endif
+    xmlNodeDumpOutputInternal(ctxt, cur);
     return(ret);
 }
 
diff --git a/third_party/libxml/src/xmlstring.c b/third_party/libxml/src/xmlstring.c
index 780c6435..62d3053 100644
--- a/third_party/libxml/src/xmlstring.c
+++ b/third_party/libxml/src/xmlstring.c
@@ -130,16 +130,18 @@
 
 int
 xmlStrcmp(const xmlChar *str1, const xmlChar *str2) {
-    register int tmp;
-
     if (str1 == str2) return(0);
     if (str1 == NULL) return(-1);
     if (str2 == NULL) return(1);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    return(strcmp((const char *)str1, (const char *)str2));
+#else
     do {
-        tmp = *str1++ - *str2;
+        int tmp = *str1++ - *str2;
         if (tmp != 0) return(tmp);
     } while (*str2++ != 0);
     return 0;
+#endif
 }
 
 /**
@@ -158,10 +160,14 @@
     if (str1 == str2) return(1);
     if (str1 == NULL) return(0);
     if (str2 == NULL) return(0);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    return(strcmp((const char *)str1, (const char *)str2) == 0);
+#else
     do {
         if (*str1++ != *str2) return(0);
     } while (*str2++);
     return(1);
+#endif
 }
 
 /**
@@ -204,18 +210,15 @@
 
 int
 xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) {
-    register int tmp;
-
     if (len <= 0) return(0);
     if (str1 == str2) return(0);
     if (str1 == NULL) return(-1);
     if (str2 == NULL) return(1);
-#ifdef __GNUC__
-    tmp = strncmp((const char *)str1, (const char *)str2, len);
-    return tmp;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    return(strncmp((const char *)str1, (const char *)str2, len));
 #else
     do {
-        tmp = *str1++ - *str2;
+        int tmp = *str1++ - *str2;
         if (tmp != 0 || --len == 0) return(tmp);
     } while (*str2++ != 0);
     return 0;
diff --git a/third_party/libxml/src/xpath.c b/third_party/libxml/src/xpath.c
index 0d5aa68b..90f10ca9 100644
--- a/third_party/libxml/src/xpath.c
+++ b/third_party/libxml/src/xpath.c
@@ -136,6 +136,17 @@
 #define XPATH_MAX_NODESET_LENGTH 10000000
 
 /*
+ * XPATH_MAX_RECRUSION_DEPTH:
+ * Maximum amount of nested functions calls when parsing or evaluating
+ * expressions
+ */
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+#define XPATH_MAX_RECURSION_DEPTH 500
+#else
+#define XPATH_MAX_RECURSION_DEPTH 5000
+#endif
+
+/*
  * TODO:
  * There are a few spots where some tests are done which depend upon ascii
  * data.  These should be enhanced for full UTF8 support (see particularly
@@ -1746,7 +1757,6 @@
 static int xmlXPathDebugObjMaxXSLTTree = 0;
 static int xmlXPathDebugObjMaxAll = 0;
 
-/* REVISIT TODO: Make this static when committing */
 static void
 xmlXPathDebugObjUsageReset(xmlXPathContextPtr ctxt)
 {
@@ -2061,7 +2071,6 @@
     xmlXPathDebugObjCounterAll--;
 }
 
-/* REVISIT TODO: Make this static when committing */
 static void
 xmlXPathDebugObjUsageDisplay(xmlXPathContextPtr ctxt)
 {
@@ -6120,9 +6129,6 @@
     ret->contextSize = -1;
     ret->proximityPosition = -1;
 
-    ret->maxDepth = INT_MAX;
-    ret->maxParserDepth = INT_MAX;
-
 #ifdef XP_DEFAULT_CACHE_ON
     if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) {
 	xmlXPathFreeContext(ret);
@@ -10950,9 +10956,13 @@
     xmlXPathContextPtr xpctxt = ctxt->context;
 
     if (xpctxt != NULL) {
-        if (xpctxt->depth >= xpctxt->maxParserDepth)
+        if (xpctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
             XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
-        xpctxt->depth += 1;
+        /*
+         * Parsing a single '(' pushes about 10 functions on the call stack
+         * before recursing!
+         */
+        xpctxt->depth += 10;
     }
 
     xmlXPathCompAndExpr(ctxt);
@@ -11667,11 +11677,11 @@
         res = xmlXPathCompOpEvalToBoolean(ctxt, filterOp, 1);
 
         if (ctxt->error != XPATH_EXPRESSION_OK)
-            goto exit;
+            break;
         if (res < 0) {
             /* Shouldn't happen */
             xmlXPathErr(ctxt, XPATH_EXPR_ERROR);
-            goto exit;
+            break;
         }
 
         if ((res != 0) && ((pos >= minPos) && (pos <= maxPos))) {
@@ -11690,15 +11700,7 @@
 
         if (res != 0) {
             if (pos == maxPos) {
-                /* Clear remaining nodes and exit loop. */
-                if (hasNsNodes) {
-                    for (i++; i < set->nodeNr; i++) {
-                        node = set->nodeTab[i];
-                        if ((node != NULL) &&
-                            (node->type == XML_NAMESPACE_DECL))
-                            xmlXPathNodeSetFreeNs((xmlNsPtr) node);
-                    }
-                }
+                i += 1;
                 break;
             }
 
@@ -11706,6 +11708,15 @@
         }
     }
 
+    /* Free remaining nodes. */
+    if (hasNsNodes) {
+        for (; i < set->nodeNr; i++) {
+            xmlNodePtr node = set->nodeTab[i];
+            if ((node != NULL) && (node->type == XML_NAMESPACE_DECL))
+                xmlXPathNodeSetFreeNs((xmlNsPtr) node);
+        }
+    }
+
     set->nodeNr = j;
 
     /* If too many elements were removed, shrink table to preserve memory. */
@@ -11726,7 +11737,6 @@
         }
     }
 
-exit:
     xpctxt->node = oldnode;
     xpctxt->doc = olddoc;
     xpctxt->contextSize = oldcs;
@@ -11791,11 +11801,11 @@
         res = xmlXPathCompOpEvalToBoolean(ctxt, filterOp, 1);
 
         if (ctxt->error != XPATH_EXPRESSION_OK)
-            goto exit;
+            break;
         if (res < 0) {
             /* Shouldn't happen */
             xmlXPathErr(ctxt, XPATH_EXPR_ERROR);
-            goto exit;
+            break;
         }
 
         if ((res != 0) && ((pos >= minPos) && (pos <= maxPos))) {
@@ -11813,10 +11823,7 @@
 
         if (res != 0) {
             if (pos == maxPos) {
-                /* Clear remaining nodes and exit loop. */
-                for (i++; i < locset->locNr; i++) {
-                    xmlXPathFreeObject(locset->locTab[i]);
-                }
+                i += 1;
                 break;
             }
 
@@ -11824,6 +11831,10 @@
         }
     }
 
+    /* Free remaining nodes. */
+    for (; i < locset->locNr; i++)
+        xmlXPathFreeObject(locset->locTab[i]);
+
     locset->locNr = j;
 
     /* If too many elements were removed, shrink table to preserve memory. */
@@ -11844,7 +11855,6 @@
         }
     }
 
-exit:
     xpctxt->node = oldnode;
     xpctxt->doc = olddoc;
     xpctxt->contextSize = oldcs;
@@ -11882,7 +11892,7 @@
                 "xmlXPathCompOpEvalPredicate: Expected a predicate\n");
             XP_ERROR(XPATH_INVALID_OPERAND);
 	}
-        if (ctxt->context->depth >= ctxt->context->maxDepth)
+        if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
             XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
         ctxt->context->depth += 1;
 	xmlXPathCompOpEvalPredicate(ctxt, &comp->steps[op->ch1], set,
@@ -12598,7 +12608,7 @@
     CHECK_ERROR0;
     if (OP_LIMIT_EXCEEDED(ctxt, 1))
         return(0);
-    if (ctxt->context->depth >= ctxt->context->maxDepth)
+    if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
         XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
     ctxt->context->depth += 1;
     comp = ctxt->comp;
@@ -12739,7 +12749,7 @@
     CHECK_ERROR0;
     if (OP_LIMIT_EXCEEDED(ctxt, 1))
         return(0);
-    if (ctxt->context->depth >= ctxt->context->maxDepth)
+    if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
         XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
     ctxt->context->depth += 1;
     comp = ctxt->comp;
@@ -12957,7 +12967,7 @@
     CHECK_ERROR0;
     if (OP_LIMIT_EXCEEDED(ctxt, 1))
         return(0);
-    if (ctxt->context->depth >= ctxt->context->maxDepth)
+    if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
         XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
     ctxt->context->depth += 1;
     comp = ctxt->comp;
@@ -13833,7 +13843,8 @@
 	do {
 	    cur = cur->parent;
 	    depth--;
-	    if ((cur == NULL) || (cur == limit))
+	    if ((cur == NULL) || (cur == limit) ||
+                (cur->type == XML_DOCUMENT_NODE))
 	        goto done;
 	    if (cur->type == XML_ELEMENT_NODE) {
 		ret = xmlStreamPop(patstream);
@@ -14104,8 +14115,7 @@
 	    }
 	}
 
-	stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH,
-			&namespaces[0]);
+	stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH, namespaces);
 	if (namespaces != NULL) {
 	    xmlFree((xmlChar **)namespaces);
 	}
@@ -14191,7 +14201,7 @@
     /* Recurse */
     ctxt = pctxt->context;
     if (ctxt != NULL) {
-        if (ctxt->depth >= ctxt->maxDepth)
+        if (ctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
             return;
         ctxt->depth += 1;
     }
@@ -14224,7 +14234,7 @@
         return(comp);
 #endif
 
-    xmlXPathInit();
+    xmlInitParser();
 
     pctxt = xmlXPathNewParserContext(str, ctxt);
     if (pctxt == NULL)
@@ -14313,7 +14323,7 @@
 
     if (comp == NULL)
 	return(-1);
-    xmlXPathInit();
+    xmlInitParser();
 
 #ifndef LIBXML_THREAD_ENABLED
     reentance++;
@@ -14458,7 +14468,7 @@
 
     CHECK_CTXT(ctx)
 
-    xmlXPathInit();
+    xmlInitParser();
 
     ctxt = xmlXPathNewParserContext(str, ctx);
     if (ctxt == NULL)
diff --git a/third_party/libxml/win32/config.h b/third_party/libxml/win32/config.h
index 324b74f..54392f49 100644
--- a/third_party/libxml/win32/config.h
+++ b/third_party/libxml/win32/config.h
@@ -5,7 +5,8 @@
 #define HAVE_STDARG_H
 #define HAVE_MALLOC_H
 #define HAVE_ERRNO_H
-#define HAVE_STDINT_H
+#define SEND_ARG2_CAST
+#define GETHOSTBYNAME_ARG_CAST
 
 #if defined(_WIN32_WCE)
 #undef HAVE_ERRNO_H
@@ -90,7 +91,7 @@
 
 #if defined(_MSC_VER)
 #define mkdir(p,m) _mkdir(p)
-#if _MSC_VER < 1900 // Cannot define this in VS 2015 and above!
+#if _MSC_VER < 1900
 #define snprintf _snprintf
 #endif
 #if _MSC_VER < 1500
diff --git a/third_party/nearby/BUILD.gn b/third_party/nearby/BUILD.gn
index e6dd3bfc..4e50ece 100644
--- a/third_party/nearby/BUILD.gn
+++ b/third_party/nearby/BUILD.gn
@@ -387,11 +387,11 @@
 source_set("core_v2_internal_mediums") {
   public_configs = [ ":nearby_include_config" ]
   sources = [
-    "src/cpp/core_v2/internal/mediums/advertisement_read_result.cc",
     "src/cpp/core_v2/internal/mediums/ble.cc",
-    "src/cpp/core_v2/internal/mediums/ble_advertisement.cc",
-    "src/cpp/core_v2/internal/mediums/ble_advertisement_header.cc",
-    "src/cpp/core_v2/internal/mediums/ble_packet.cc",
+    "src/cpp/core_v2/internal/mediums/ble_v2/advertisement_read_result.cc",
+    "src/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement.cc",
+    "src/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_header.cc",
+    "src/cpp/core_v2/internal/mediums/ble_v2/ble_packet.cc",
     "src/cpp/core_v2/internal/mediums/bloom_filter.cc",
     "src/cpp/core_v2/internal/mediums/bluetooth_classic.cc",
     "src/cpp/core_v2/internal/mediums/bluetooth_radio.cc",
@@ -401,12 +401,12 @@
     "src/cpp/core_v2/internal/mediums/wifi_lan.cc",
   ]
   public = [
-    "src/cpp/core_v2/internal/mediums/advertisement_read_result.h",
     "src/cpp/core_v2/internal/mediums/ble.h",
-    "src/cpp/core_v2/internal/mediums/ble_advertisement.h",
-    "src/cpp/core_v2/internal/mediums/ble_advertisement_header.h",
-    "src/cpp/core_v2/internal/mediums/ble_packet.h",
-    "src/cpp/core_v2/internal/mediums/ble_peripheral.h",
+    "src/cpp/core_v2/internal/mediums/ble_v2/advertisement_read_result.h",
+    "src/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement.h",
+    "src/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_header.h",
+    "src/cpp/core_v2/internal/mediums/ble_v2/ble_packet.h",
+    "src/cpp/core_v2/internal/mediums/ble_v2/ble_peripheral.h",
     "src/cpp/core_v2/internal/mediums/bloom_filter.h",
     "src/cpp/core_v2/internal/mediums/bluetooth_classic.h",
     "src/cpp/core_v2/internal/mediums/bluetooth_radio.h",
diff --git a/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt b/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt
index caa71ec1..a9b9409 100644
--- a/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt
+++ b/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt
@@ -21,6 +21,7 @@
 
 # Exclude tools that do not ship in the Chrome binary. Can't depend on //base.
 base/android/linker/
+chrome/chrome_cleaner/
 tools/
 net/tools/
 
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec
index a2f239c6..8c4f7b4 100644
--- a/tools/gritsettings/resource_ids.spec
+++ b/tools/gritsettings/resource_ids.spec
@@ -134,9 +134,6 @@
     "includes": [1480],
     "structures": [1500],
   },
-  "chrome/browser/resources/extensions/extensions_resources_vulcanized.grd": {
-    "includes": [1520],
-  },
   "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/extensions/extensions_resources.grd": {
     "META": {"sizes": {"includes": [50],}},
     "includes": [1540],
diff --git a/tools/metrics/histograms/OWNERS b/tools/metrics/histograms/OWNERS
index 6ca679d6..0f83aa2f 100644
--- a/tools/metrics/histograms/OWNERS
+++ b/tools/metrics/histograms/OWNERS
@@ -1,27 +1,9 @@
-# Core Metrics Owners
-#
-# Note: Please send CLs to chromium-metrics-reviews@google.com rather than to
-# specific individuals from the list of core metrics owners. These CLs will be
-# automatically reassigned to a reviewer within about 5 minutes. This approach
-# helps our team to load-balance incoming reviews. Googlers can read more about
-# this at go/gwsq-gerrit.
-per-file histograms.xml=file://base/metrics/OWNERS
 # Extending enums by adding new buckets is allowed without OWNERS review, but
-# you should add a metrics reviewer if you are changing the semantics of existing
-# buckets.
+# you should add a metrics reviewer if you are changing the semantics of
+# existing buckets.
 per-file enums.xml=*
 
-# Prefer chromium-metrics-reviews@google.com instead.
-# Use the following owners only if:
-#  - You work in the same area as them.
-#  - They are already a good reviewer for the non-metrics part of the CL.
-per-file histograms.xml=alexilin@chromium.org
-per-file histograms.xml=altimin@chromium.org # Scheduling-related metrics.
-per-file histograms.xml=csharrison@chromium.org
-per-file histograms.xml=cthomp@chromium.org  # For security-related metrics only.
-per-file histograms.xml=dschinazi@chromium.org  # For networking-related metrics only.
-per-file histograms.xml=schenney@chromium.org
-per-file histograms.xml=tbansal@chromium.org
-per-file histograms.xml=tby@chromium.org # For chrome knowledge team metrics only.
-per-file histograms.xml=chrome-metrics-team+robot@google.com # For bot updates to expiry.
+# The top-level histograms.xml file is deprecated and should not be modified.
+# It's temporarily still present because some tools have the filename hardcoded.
+per-file histograms.xml=file://base/metrics/OWNERS
 per-file histograms.xml=set noparent
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index f4722ce4..cbaf091 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -25046,6 +25046,7 @@
   <int value="1519" label="VIRTUALKEYBOARDPRIVATE_OPENSUGGESTIONSETTINGS"/>
   <int value="1520" label="ACCESSIBILITY_PRIVATE_ENABLEPOINTSCAN"/>
   <int value="1521" label="AUTOTESTPRIVATE_ACTIVATEADJACENTDESKSTOTARGETINDEX"/>
+  <int value="1522" label="DECLARATIVENETREQUEST_GETAVAILABLESTATICRULECOUNT"/>
 </enum>
 
 <enum name="ExtensionIconState">
@@ -72354,6 +72355,7 @@
   <int value="21" label="Page state doesn't require translation"/>
   <int value="22"
       label="Identical language translation, use source language Unknown"/>
+  <int value="23" label="Disabled because Autofill Assistant is running."/>
 </enum>
 
 <enum name="TranslateLanguage">
diff --git a/tools/metrics/histograms/histograms_xml/OWNERS b/tools/metrics/histograms/histograms_xml/OWNERS
new file mode 100644
index 0000000..8ec30c7
--- /dev/null
+++ b/tools/metrics/histograms/histograms_xml/OWNERS
@@ -0,0 +1,19 @@
+# Core Metrics Owners
+#
+# Note: Please send CLs to chromium-metrics-reviews@google.com rather than to
+# specific individuals from the list of core metrics owners. These CLs will be
+# automatically reassigned to a reviewer within about 5 minutes. This approach
+# helps our team to load-balance incoming reviews. Googlers can read more about
+# this at go/gwsq-gerrit.
+file://base/metrics/OWNERS
+
+# Prefer chromium-metrics-reviews@google.com instead.
+# Use the following owners only if:
+#  - You work in the same area as them.
+#  - They are already a good reviewer for the non-metrics part of the CL.
+cthomp@chromium.org  # For security-related metrics only.
+
+chrome-metrics-team+robot@google.com # For bot updates to expiry.
+
+# All metrics changes should be reviewed by metrics reviewers.
+set noparent
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv
index 78d5811..791b1278 100644
--- a/tools/perf/benchmark.csv
+++ b/tools/perf/benchmark.csv
@@ -3,6 +3,7 @@
 Googlers can view additional information about internal perf infrastructure at,https://goto.google.com/chrome-benchmarking-sheet
 Benchmark name,Individual owners,Component,Documentation,Tags
 UNSCHEDULED_blink_perf.service_worker,"shimazu@chromium.org, falken@chromium.org, ting.shao@intel.com",Blink>ServiceWorker,https://bit.ly/blink-perf-benchmarks,
+UNSCHEDULED_system_health.weblayer_startup,"cduvall@chromium.org, weblayer-team@chromium.org",Internals>WebLayer,https://bit.ly/36XBtpn,2016
 angle_perftests,"jmadill@chromium.org, chrome-gpu-perf-owners@chromium.org",Internals>GPU>ANGLE,,
 base_perftests,"skyostil@chromium.org, gab@chromium.org",Internals>SequenceManager,https://chromium.googlesource.com/chromium/src/+/HEAD/base/README.md#performance-testing,
 blink_perf.accessibility,dmazzoni@chromium.org,Blink>Accessibility,https://bit.ly/blink-perf-benchmarks,all
diff --git a/tools/perf/benchmarks/system_health.py b/tools/perf/benchmarks/system_health.py
index 88d2d3bc..fdcdcb58 100644
--- a/tools/perf/benchmarks/system_health.py
+++ b/tools/perf/benchmarks/system_health.py
@@ -246,3 +246,30 @@
   @classmethod
   def Name(cls):
     return 'system_health.webview_startup'
+
+
+@benchmark.Info(emails=['cduvall@chromium.org', 'weblayer-team@chromium.org'],
+                component='Internals>WebLayer',
+                documentation_url='https://bit.ly/36XBtpn')
+class WebLayerStartupSystemHealthBenchmark(WebviewStartupSystemHealthBenchmark):
+  """WebLayer startup time benchmark
+
+  Benchmark that measures how long WebLayer takes to start up
+  and load a blank page.
+  """
+  # TODO(rmhasan): Remove the SUPPORTED_PLATFORMS lists.
+  # SUPPORTED_PLATFORMS is deprecated, please put system specifier tags
+  # from expectations.config in SUPPORTED_PLATFORM_TAGS.
+  # TODO(crbug.com/1137468): Add WEBLAYER to telemetry platforms.
+  SUPPORTED_PLATFORM_TAGS = [platforms.MOBILE]
+  SUPPORTED_PLATFORMS = [story.expectations.ALL_MOBILE]
+
+  def CreateCoreTimelineBasedMeasurementOptions(self):
+    options = super(WebLayerStartupSystemHealthBenchmark,
+                    self).CreateCoreTimelineBasedMeasurementOptions()
+    options.config.atrace_config.app_name = 'org.chromium.weblayer.shell'
+    return options
+
+  @classmethod
+  def Name(cls):
+    return 'UNSCHEDULED_system_health.weblayer_startup'
diff --git a/tools/perf/benchmarks/system_health_unittest.py b/tools/perf/benchmarks/system_health_unittest.py
index ace7395..a6ea0fdc 100644
--- a/tools/perf/benchmarks/system_health_unittest.py
+++ b/tools/perf/benchmarks/system_health_unittest.py
@@ -28,12 +28,17 @@
 
   def testNamePrefix(self):
     for b in _GetAllSystemHealthBenchmarks():
+      # TODO(crbug.com/1137468): Right now this has the UNSCHEDULED_ prefix.
+      if b is system_health_benchmark.WebLayerStartupSystemHealthBenchmark:
+        continue
       self.assertTrue(
           b.Name().startswith('system_health.'),
           '%r must have name starting with "system_health." prefix' % b)
 
   def testSystemHealthStorySetIsUsed(self):
     for b in _GetAllSystemHealthBenchmarks():
+      if b is system_health_benchmark.WebLayerStartupSystemHealthBenchmark:
+        continue
       if b is system_health_benchmark.WebviewStartupSystemHealthBenchmark:
         continue
       self.assertIsInstance(
diff --git a/ui/accessibility/ax_event_generator.cc b/ui/accessibility/ax_event_generator.cc
index 78e9922..fd39eaa1 100644
--- a/ui/accessibility/ax_event_generator.cc
+++ b/ui/accessibility/ax_event_generator.cc
@@ -357,24 +357,10 @@
       if (node != tree->root())
         AddEvent(node, Event::NAME_CHANGED);
 
-      // If it's in a live region, fire live region events.
       if (node->data().HasStringAttribute(
               ax::mojom::StringAttribute::kContainerLiveStatus)) {
         FireLiveRegionEvents(node);
       }
-
-      // If it's a change to static text, and it's in an editable text region,
-      // fire an event on the editable root.
-      if (ui::IsText(node->data().role) &&
-          node->data().HasState(ax::mojom::State::kEditable)) {
-        AXNode* container = node;
-        while (container && !container->data().GetBoolAttribute(
-                                ax::mojom::BoolAttribute::kEditableRoot)) {
-          container = container->parent();
-        }
-        if (container)
-          AddEvent(container, Event::EDITABLE_TEXT_CHANGED);
-      }
       break;
     case ax::mojom::StringAttribute::kPlaceholder:
       AddEvent(node, Event::PLACEHOLDER_CHANGED);
@@ -1055,8 +1041,6 @@
       return "documentTitleChanged";
     case AXEventGenerator::Event::DROPEFFECT_CHANGED:
       return "dropeffectChanged";
-    case ui::AXEventGenerator::Event::EDITABLE_TEXT_CHANGED:
-      return "editableTextChanged";
     case AXEventGenerator::Event::ENABLED_CHANGED:
       return "enabledChanged";
     case AXEventGenerator::Event::EXPANDED:
diff --git a/ui/accessibility/ax_event_generator.h b/ui/accessibility/ax_event_generator.h
index f36f90b8..34447ba 100644
--- a/ui/accessibility/ax_event_generator.h
+++ b/ui/accessibility/ax_event_generator.h
@@ -46,7 +46,6 @@
     DOCUMENT_SELECTION_CHANGED,
     DOCUMENT_TITLE_CHANGED,
     DROPEFFECT_CHANGED,
-    EDITABLE_TEXT_CHANGED,
     ENABLED_CHANGED,
     EXPANDED,
     FOCUS_CHANGED,
diff --git a/ui/accessibility/ax_event_generator_unittest.cc b/ui/accessibility/ax_event_generator_unittest.cc
index 2451869..f6a17b2e 100644
--- a/ui/accessibility/ax_event_generator_unittest.cc
+++ b/ui/accessibility/ax_event_generator_unittest.cc
@@ -2350,37 +2350,4 @@
                          1)));
 }
 
-TEST(AXEventGeneratorTest, EditableTextChanged) {
-  AXTreeUpdate initial_state;
-  initial_state.root_id = 1;
-  initial_state.nodes.resize(3);
-  initial_state.nodes[0].id = 1;
-  initial_state.nodes[0].child_ids.push_back(2);
-  initial_state.nodes[1].id = 2;
-  initial_state.nodes[1].role = ax::mojom::Role::kTextField;
-  initial_state.nodes[1].AddState(ax::mojom::State::kEditable);
-  initial_state.nodes[1].AddBoolAttribute(
-      ax::mojom::BoolAttribute::kEditableRoot, true);
-  initial_state.nodes[1].child_ids.push_back(3);
-  initial_state.nodes[2].id = 3;
-  initial_state.nodes[2].role = ax::mojom::Role::kStaticText;
-  initial_state.nodes[2].AddState(ax::mojom::State::kEditable);
-  initial_state.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kName,
-                                            "Before");
-  AXTree tree(initial_state);
-
-  AXEventGenerator event_generator(&tree);
-  AXTreeUpdate update = initial_state;
-  update.nodes[2].string_attributes.clear();
-  update.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kName,
-                                     "After");
-
-  ASSERT_TRUE(tree.Unserialize(update));
-  EXPECT_THAT(
-      event_generator,
-      UnorderedElementsAre(
-          HasEventAtNode(AXEventGenerator::Event::EDITABLE_TEXT_CHANGED, 2),
-          HasEventAtNode(AXEventGenerator::Event::NAME_CHANGED, 3)));
-}
-
 }  // namespace ui
diff --git a/ui/base/models/dialog_model.h b/ui/base/models/dialog_model.h
index c01b8c9..26e8293 100644
--- a/ui/base/models/dialog_model.h
+++ b/ui/base/models/dialog_model.h
@@ -111,8 +111,13 @@
     // with the DialogModel so uses of it will not result in use-after-frees.
     DialogModel* model() { return model_.get(); }
 
-    Builder& SetShowCloseButton(bool show_close_button) {
-      model_->show_close_button_ = show_close_button;
+    // Overrides the close-x use for the dialog. Should be avoided as the
+    // close-x is generally derived from dialog modality. Kept to allow
+    // conversion of dialogs that currently do not allow style.
+    // TODO(pbos): Propose UX updates to existing dialogs that require this,
+    // then remove OverrideShowCloseButton().
+    Builder& OverrideShowCloseButton(bool show_close_button) {
+      model_->override_show_close_button_ = show_close_button;
       return *this;
     }
 
@@ -267,8 +272,9 @@
     host_ = host;
   }
 
-  bool show_close_button(util::PassKey<DialogModelHost>) const {
-    return show_close_button_;
+  const base::Optional<bool>& override_show_close_button(
+      util::PassKey<DialogModelHost>) const {
+    return override_show_close_button_;
   }
 
   const base::string16& title(util::PassKey<DialogModelHost>) const {
@@ -318,7 +324,7 @@
   std::unique_ptr<DialogModelDelegate> delegate_;
   DialogModelHost* host_ = nullptr;
 
-  bool show_close_button_ = false;
+  base::Optional<bool> override_show_close_button_;
   bool close_on_deactivate_ = true;
   base::string16 title_;
 
diff --git a/ui/chromeos/file_manager_strings.grdp b/ui/chromeos/file_manager_strings.grdp
index 3c035508..0334e6f 100644
--- a/ui/chromeos/file_manager_strings.grdp
+++ b/ui/chromeos/file_manager_strings.grdp
@@ -266,8 +266,11 @@
     <ph name="NUMBER_OF_FILES">$1<ex>3</ex></ph> items
   </message>
 
+  <message name="IDS_FILE_BROWSER_ARCHIVE_MOUNT_MESSAGE" desc="Message shown when opening an archive takes a long time.">
+    Opening "<ph name="PATH">$1<ex>zipfile.zip</ex></ph>"
+  </message>
   <message name="IDS_FILE_BROWSER_ARCHIVE_MOUNT_FAILED" desc="Error message when an archive mount operation failed.">
-    Unable to open "<ph name="PATH">$1<ex>zipfile.zip</ex></ph>"
+    Could not open "<ph name="PATH">$1<ex>zipfile.zip</ex></ph>"
   </message>
   <message name="IDS_FILE_BROWSER_UNMOUNT_FAILED" desc="Title of the error dialog when device unmount operation failed.">
    <ph name="BEGIN_BOLD">&lt;b&gt;</ph>Don't remove your device just yet!<ph name="END_BOLD">&lt;/b&gt;</ph>
@@ -1305,11 +1308,11 @@
   <message name="IDS_FILE_BROWSER_MESSAGE_FOLDER_SHARED_WITH_CROSTINI" desc="Message shown in FilesApp message bar when a user has shared a folder with the crostini container.">
     This folder is shared with Linux
   </message>
-  <message name="IDS_FILE_BROWSER_MESSAGE_FOLDER_SHARED_WITH_CROSTINI_AND_PLUGIN_VM" desc="Message shown in FilesApp message bar when a user has shared a folder with the crostini container and Windows.">
-    This folder is shared with Linux and Windows
+  <message name="IDS_FILE_BROWSER_MESSAGE_FOLDER_SHARED_WITH_CROSTINI_AND_PLUGIN_VM" desc="Message shown in FilesApp message bar when a user has shared a folder with the crostini container and with Parallels. Do not translate 'Linux' or 'Parallels Desktop'">
+    This folder is shared with Linux and Parallels Desktop
   </message>
-  <message name="IDS_FILE_BROWSER_MESSAGE_FOLDER_SHARED_WITH_PLUGIN_VM" desc="Message shown in FilesApp message bar when a user has shared a folder with Windows.">
-    This folder is shared with Windows
+  <message name="IDS_FILE_BROWSER_MESSAGE_FOLDER_SHARED_WITH_PLUGIN_VM" desc="Message shown in FilesApp message bar when a user has shared a folder with Parallels. Do not translate 'Parallels Desktop'">
+    This folder is shared with Parallels Desktop
   </message>
 
   <message name="IDS_FILE_BROWSER_FOLDER" desc="Folder entry type">
diff --git a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_ARCHIVE_MOUNT_FAILED.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_ARCHIVE_MOUNT_FAILED.png.sha1
index b6cf96b3..49b038d 100644
--- a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_ARCHIVE_MOUNT_FAILED.png.sha1
+++ b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_ARCHIVE_MOUNT_FAILED.png.sha1
@@ -1 +1 @@
-0b5ea4fdc5c10315f7a11baece644b3dc02b1d92
\ No newline at end of file
+0740bd12187c63f2686f5af88225e6a9ad1879f7
\ No newline at end of file
diff --git a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_ARCHIVE_MOUNT_MESSAGE.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_ARCHIVE_MOUNT_MESSAGE.png.sha1
new file mode 100644
index 0000000..f8f8a26
--- /dev/null
+++ b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_ARCHIVE_MOUNT_MESSAGE.png.sha1
@@ -0,0 +1 @@
+8e346843dd34457777c8a3ab982721a41bfd01f6
\ No newline at end of file
diff --git a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_MESSAGE_FOLDER_SHARED_WITH_CROSTINI_AND_PLUGIN_VM.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_MESSAGE_FOLDER_SHARED_WITH_CROSTINI_AND_PLUGIN_VM.png.sha1
index 7daa6d0..2d2894ec 100644
--- a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_MESSAGE_FOLDER_SHARED_WITH_CROSTINI_AND_PLUGIN_VM.png.sha1
+++ b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_MESSAGE_FOLDER_SHARED_WITH_CROSTINI_AND_PLUGIN_VM.png.sha1
@@ -1 +1 @@
-9a020b433046604e8f2886847af5b30abbc5081d
\ No newline at end of file
+25124744b4a04a2513245f260426ad671f1f632c
\ No newline at end of file
diff --git a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_MESSAGE_FOLDER_SHARED_WITH_PLUGIN_VM.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_MESSAGE_FOLDER_SHARED_WITH_PLUGIN_VM.png.sha1
index f1fb0cf..22895ee 100644
--- a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_MESSAGE_FOLDER_SHARED_WITH_PLUGIN_VM.png.sha1
+++ b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_MESSAGE_FOLDER_SHARED_WITH_PLUGIN_VM.png.sha1
@@ -1 +1 @@
-0b9139b5c1a73f00c0a22dd763cb9646a2d09c9b
\ No newline at end of file
+3605b570180c1bc8f9bf8b0582184fe2651f5c0e
\ No newline at end of file
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks.js b/ui/file_manager/file_manager/foreground/js/file_tasks.js
index ecceb31..1d3a7b3 100644
--- a/ui/file_manager/file_manager/foreground/js/file_tasks.js
+++ b/ui/file_manager/file_manager/foreground/js/file_tasks.js
@@ -868,6 +868,17 @@
    * @private
    */
   async mountArchive_(url) {
+    const filename = util.extractFilePath(url).split('/').pop();
+
+    const item = new ProgressCenterItem();
+    item.id = 'mount-' + url;
+    item.type = ProgressItemType.MOUNT_ARCHIVE;
+    item.message = strf('ARCHIVE_MOUNT_MESSAGE', filename);
+
+    // Display progress panel.
+    item.state = ProgressItemState.PROGRESSING;
+    this.progressCenter_.updateItem(item);
+
     // First time, try without providing a password.
     try {
       return await this.volumeManager_.mountArchive(url);
@@ -876,13 +887,16 @@
       if (error !== VolumeManagerCommon.VolumeError.NEED_PASSWORD) {
         throw error;
       }
+    } finally {
+      // Remove progress panel.
+      item.state = ProgressItemState.COMPLETED;
+      this.progressCenter_.updateItem(item);
     }
 
     // We need a password.
     const unlock = await this.mutex_.lock();
     try {
       /** @type {?string} */ let password = null;
-      const filename = util.extractFilePath(url).split('/').pop();
       while (true) {
         // Ask for password.
         do {
@@ -890,6 +904,10 @@
               await this.ui_.passwordDialog.askForPassword(filename, password);
         } while (!password);
 
+        // Display progress panel.
+        item.state = ProgressItemState.PROGRESSING;
+        this.progressCenter_.updateItem(item);
+
         // Mount archive with password.
         try {
           return await this.volumeManager_.mountArchive(url, password);
@@ -898,6 +916,10 @@
           if (error !== VolumeManagerCommon.VolumeError.NEED_PASSWORD) {
             throw error;
           }
+        } finally {
+          // Remove progress panel.
+          item.state = ProgressItemState.COMPLETED;
+          this.progressCenter_.updateItem(item);
         }
       }
     } finally {
@@ -916,6 +938,7 @@
   async mountArchiveAndChangeDirectory_(tracker, url) {
     try {
       const volumeInfo = await this.mountArchive_(url);
+
       if (tracker.hasChanged) {
         return;
       }
@@ -938,13 +961,12 @@
       }
 
       const filename = util.extractFilePath(url).split('/').pop();
-
-      const errorItem = new ProgressCenterItem();
-      errorItem.id = 'cannot-mount-' + url;
-      errorItem.type = ProgressItemType.MOUNT_ARCHIVE;
-      errorItem.message = strf('ARCHIVE_MOUNT_FAILED', filename);
-      errorItem.state = ProgressItemState.ERROR;
-      this.progressCenter_.updateItem(errorItem);
+      const item = new ProgressCenterItem();
+      item.id = 'cannot-mount-' + url;
+      item.type = ProgressItemType.MOUNT_ARCHIVE;
+      item.message = strf('ARCHIVE_MOUNT_FAILED', filename);
+      item.state = ProgressItemState.ERROR;
+      this.progressCenter_.updateItem(item);
 
       console.error(`Cannot mount '${url}':`);
       console.error(error);
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.cc b/ui/views/bubble/bubble_dialog_delegate_view.cc
index 7024d3e0..6e2593fc 100644
--- a/ui/views/bubble/bubble_dialog_delegate_view.cc
+++ b/ui/views/bubble/bubble_dialog_delegate_view.cc
@@ -408,6 +408,11 @@
     client_view_->layer()->SetIsFastRoundedCorner(true);
   }
 
+  if (fixed_width_) {
+    // TODO(pbos): Make sure this reacts to or NOTREACHED()s changes to margins.
+    client_view_->set_fixed_width(fixed_width_ - margins().width());
+  }
+
   return client_view_;
 }
 
@@ -528,6 +533,12 @@
     UpdateHighlightedButton(true);
 }
 
+void BubbleDialogDelegate::SetFixedWidth(int width) {
+  // SetFixedWidth should be called before |client_view_| is created.
+  DCHECK(!client_view_);
+  fixed_width_ = width;
+}
+
 void BubbleDialogDelegate::SetArrow(BubbleBorder::Arrow arrow) {
   SetArrowWithoutResizing(arrow);
   // If SetArrow() is called before CreateWidget(), there's no need to update
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.h b/ui/views/bubble/bubble_dialog_delegate_view.h
index bd9cc7b0..a05f22b 100644
--- a/ui/views/bubble/bubble_dialog_delegate_view.h
+++ b/ui/views/bubble/bubble_dialog_delegate_view.h
@@ -174,6 +174,10 @@
   // view.
   void SetHighlightedButton(Button* highlighted_button);
 
+  // Set a fixed width for the dialog. The client view will size itself to
+  // preferred height for this width, minus dialog margins.
+  void SetFixedWidth(int width);
+
   // The bubble's parent window - this can only be usefully set before creating
   // the bubble's widget. If there is one, the bubble will be stacked above it,
   // and it will become the Views parent window for the bubble.
@@ -335,6 +339,9 @@
   bool focus_traversable_from_anchor_view_ = true;
   ViewTracker highlighted_button_tracker_;
 
+  // Use a fixed dialog width instead of the |client_view_| preferred size.
+  int fixed_width_ = 0;
+
   // Insets applied to the |anchor_view_| bounds.
   gfx::Insets anchor_view_insets_;
 
diff --git a/ui/views/bubble/bubble_dialog_model_host.cc b/ui/views/bubble/bubble_dialog_model_host.cc
index 56de35c..89b31d4 100644
--- a/ui/views/bubble/bubble_dialog_model_host.cc
+++ b/ui/views/bubble/bubble_dialog_model_host.cc
@@ -134,12 +134,20 @@
   SetButtons(button_mask);
 
   SetTitle(model_->title(GetPassKey()));
-  SetShowCloseButton(model_->show_close_button(GetPassKey()));
+  if (model_->override_show_close_button(GetPassKey())) {
+    SetShowCloseButton(*model_->override_show_close_button(GetPassKey()));
+  } else {
+    SetShowCloseButton(!IsModalDialog());
+  }
   if (model_->is_alert_dialog(GetPassKey()))
     SetAccessibleRole(ax::mojom::Role::kAlertDialog);
 
   set_close_on_deactivate(model_->close_on_deactivate(GetPassKey()));
 
+  SetFixedWidth(LayoutProvider::Get()->GetDistanceMetric(
+      anchor_view ? views::DISTANCE_BUBBLE_PREFERRED_WIDTH
+                  : views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
+
   AddInitialFields();
 }
 
@@ -186,15 +194,6 @@
   }
 }
 
-gfx::Size BubbleDialogModelHost::CalculatePreferredSize() const {
-  const int width = LayoutProvider::Get()->GetDistanceMetric(
-                        GetModalType() == ui::MODAL_TYPE_NONE
-                            ? views::DISTANCE_BUBBLE_PREFERRED_WIDTH
-                            : views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH) -
-                    margins().width();
-  return gfx::Size(width, GetHeightForWidth(width));
-}
-
 void BubbleDialogModelHost::Close() {
   DCHECK(model_);
   DCHECK(GetWidget());
@@ -489,6 +488,10 @@
   return text_label;
 }
 
+bool BubbleDialogModelHost::IsModalDialog() const {
+  return GetModalType() != ui::MODAL_TYPE_NONE;
+}
+
 BEGIN_METADATA(BubbleDialogModelHost, BubbleDialogDelegateView)
 END_METADATA
 
diff --git a/ui/views/bubble/bubble_dialog_model_host.h b/ui/views/bubble/bubble_dialog_model_host.h
index 912092e9..d900f5b 100644
--- a/ui/views/bubble/bubble_dialog_model_host.h
+++ b/ui/views/bubble/bubble_dialog_model_host.h
@@ -46,7 +46,6 @@
   // GetInitiallyFocusedView().
   View* GetInitiallyFocusedView() override;
   void OnDialogInitialized() override;
-  gfx::Size CalculatePreferredSize() const override;
 
   // ui::DialogModelHost:
   void Close() override;
@@ -75,6 +74,8 @@
 
   View* FieldToView(ui::DialogModelField* field);
 
+  bool IsModalDialog() const;
+
   std::unique_ptr<ui::DialogModel> model_;
   base::flat_map<ui::DialogModelField*, View*> field_to_view_;
   std::vector<PropertyChangedSubscription> property_changed_subscriptions_;
diff --git a/ui/views/window/client_view.cc b/ui/views/window/client_view.cc
index 0daaa19..bfb78f0 100644
--- a/ui/views/window/client_view.cc
+++ b/ui/views/window/client_view.cc
@@ -40,7 +40,15 @@
 gfx::Size ClientView::CalculatePreferredSize() const {
   // |contents_view_| is allowed to be NULL up until the point where this view
   // is attached to a Container.
-  return contents_view_ ? contents_view_->GetPreferredSize() : gfx::Size();
+  if (!contents_view_)
+    return gfx::Size();
+
+  if (fixed_width_) {
+    return gfx::Size(fixed_width_,
+                     contents_view_->GetHeightForWidth(fixed_width_));
+  }
+
+  return contents_view_->GetPreferredSize();
 }
 
 gfx::Size ClientView::GetMaximumSize() const {
diff --git a/ui/views/window/client_view.h b/ui/views/window/client_view.h
index 0f69d64..b95430e 100644
--- a/ui/views/window/client_view.h
+++ b/ui/views/window/client_view.h
@@ -30,6 +30,8 @@
   ClientView(Widget* widget, View* contents_view);
   ~ClientView() override = default;
 
+  void set_fixed_width(int width) { fixed_width_ = width; }
+
   // Returned value signals whether the Widget can be closed. Specialized
   // ClientView subclasses can override this default behavior to allow the
   // close to be blocked until the user corrects mistakes, accepts a warning
@@ -71,6 +73,8 @@
  private:
   // The View that this ClientView contains.
   View* contents_view_;
+
+  int fixed_width_ = 0;
 };
 
 }  // namespace views
diff --git a/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html b/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html
index 1a11bd4b..911c83b9 100644
--- a/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html
+++ b/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html
@@ -161,7 +161,7 @@
     <div id="label-container" aria-hidden="true" part="label-container">
       <slot></slot>
     </div>
-    <div id="ariaDescription">[[ariaDescription]]</div>
+    <div id="ariaDescription" aria-hidden="true">[[ariaDescription]]</div>
   </template>
   <script src="cr_checkbox.js"></script>
 </dom-module>
diff --git a/weblayer/browser/translate_client_impl.cc b/weblayer/browser/translate_client_impl.cc
index 89d1b13e..450cce9 100644
--- a/weblayer/browser/translate_client_impl.cc
+++ b/weblayer/browser/translate_client_impl.cc
@@ -132,6 +132,11 @@
   return translate::IsTranslatableURL(url);
 }
 
+bool TranslateClientImpl::IsAutofillAssistantRunning() const {
+  // TODO(crbug.com/1051559): Revise if/when WebLayer supports Autobot.
+  return false;
+}
+
 void TranslateClientImpl::ShowReportLanguageDetectionErrorUI(
     const GURL& report_url) {
   NOTREACHED();
diff --git a/weblayer/browser/translate_client_impl.h b/weblayer/browser/translate_client_impl.h
index 9970924..592336d 100644
--- a/weblayer/browser/translate_client_impl.h
+++ b/weblayer/browser/translate_client_impl.h
@@ -64,6 +64,7 @@
                        bool triggered_from_menu) override;
   bool IsTranslatableURL(const GURL& url) override;
   void ShowReportLanguageDetectionErrorUI(const GURL& report_url) override;
+  bool IsAutofillAssistantRunning() const override;
 
   // ContentTranslateDriver::Observer implementation.
   void OnLanguageDetermined(
diff --git a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/TelemetryActivity.java b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/TelemetryActivity.java
index 7495340..8cef642e 100644
--- a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/TelemetryActivity.java
+++ b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/TelemetryActivity.java
@@ -6,6 +6,7 @@
 
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Trace;
 import android.text.InputType;
 import android.view.View;
 import android.view.ViewGroup;
@@ -21,6 +22,8 @@
 import androidx.fragment.app.FragmentTransaction;
 
 import org.chromium.weblayer.Browser;
+import org.chromium.weblayer.Navigation;
+import org.chromium.weblayer.NavigationCallback;
 import org.chromium.weblayer.Profile;
 import org.chromium.weblayer.Tab;
 import org.chromium.weblayer.TabCallback;
@@ -37,6 +40,12 @@
 public class TelemetryActivity extends FragmentActivity {
     private static final String KEY_MAIN_VIEW_ID = "mainViewId";
 
+    // The trace tag names are the same as WebView's telemetry activity so the perf metric logic can
+    // be shared between them.
+    private static final String START_UP_TRACE_TAG = "WebViewStartupInterval";
+    private static final String LOAD_URL_TRACE_TAG = "WebViewBlankUrlLoadInterval";
+    private static final String DUMMY_TRACE_TAG = "WebViewDummyInterval";
+
     private Profile mProfile;
     private Fragment mFragment;
     private Browser mBrowser;
@@ -77,6 +86,14 @@
         mTopContentsContainer.addView(
                 mUrlView, new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0));
 
+        Trace.beginSection(START_UP_TRACE_TAG);
+
+        // TODO(aluo): Use async tracing to avoid having to do this
+        // dummyTraceTag is needed here to prevent code in Android intended to
+        // end activityStart from ending loadUrlTraceTag prematurely,
+        // see crbug/919221
+        Trace.beginSection(DUMMY_TRACE_TAG);
+
         // If activity is re-created during process restart, FragmentManager attaches
         // BrowserFragment immediately, resulting in synchronous init. By the time this line
         // executes, the synchronous init has already happened, so WebLayer#createAsync will
@@ -102,6 +119,11 @@
     }
 
     private void onWebLayerReady(WebLayer webLayer) {
+        // Ends START_UP_TRACE_TAG
+        Trace.endSection();
+        // Ends activityStart
+        Trace.endSection();
+
         if (mBrowser != null || isFinishing() || isDestroyed()) return;
 
         webLayer.setRemoteDebuggingEnabled(true);
@@ -113,6 +135,14 @@
         mBrowser.setTopView(mTopContentsContainer);
         setTab(mBrowser.getActiveTab());
 
+        Trace.beginSection(LOAD_URL_TRACE_TAG);
+        mTab.getNavigationController().registerNavigationCallback(new NavigationCallback() {
+            @Override
+            public void onNavigationCompleted(Navigation navigation) {
+                // Ends LOAD_URL_TRACE_TAG
+                Trace.endSection();
+            }
+        });
         if (getIntent() != null) {
             mTab.getNavigationController().navigate(Uri.parse(getIntent().getDataString()));
         }